diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 875 |
1 files changed, 619 insertions, 256 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index d56b0ea7ad..0d5dc08b03 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -8,10 +8,27 @@ #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include <memory> + #include "common/MemoryBuffer.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +namespace +{ + +template <typename T> +GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index) +{ + return reinterpret_cast<const T *>(data)[index]; +} +typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index); +} + #if defined(ANGLE_MINGW32_COMPAT) typedef enum D3D11_MAP_FLAG { D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000 @@ -20,32 +37,33 @@ typedef enum D3D11_MAP_FLAG { namespace rx { - PackPixelsParams::PackPixelsParams() - : format(GL_NONE), - type(GL_NONE), - outputPitch(0), - packBuffer(NULL), - offset(0) -{} - -PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn, - const gl::PixelPackState &packIn, ptrdiff_t offsetIn) - : area(areaIn), - format(formatIn), - type(typeIn), - outputPitch(outputPitchIn), - packBuffer(packIn.pixelBuffer.get()), - pack(packIn.alignment, packIn.reverseRowOrder), - offset(offsetIn) -{} + : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0) +{ +} + +PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, + GLenum formatIn, + GLenum typeIn, + GLuint outputPitchIn, + const gl::PixelPackState &packIn, + ptrdiff_t offsetIn) + : area(areaIn), + format(formatIn), + type(typeIn), + outputPitch(outputPitchIn), + packBuffer(packIn.pixelBuffer.get()), + pack(packIn.alignment, packIn.reverseRowOrder), + offset(offsetIn) +{ +} namespace gl_d3d11 { D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) { - bool readBit = ((access & GL_MAP_READ_BIT) != 0); + bool readBit = ((access & GL_MAP_READ_BIT) != 0); bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); ASSERT(readBit || writeBit); @@ -71,7 +89,6 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) return D3D11_MAP_READ; } } - } // Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points @@ -91,8 +108,10 @@ class Buffer11::BufferStorage : angle::NonCopyable virtual bool isMappable() const = 0; - virtual bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) = 0; + virtual bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) = 0; virtual gl::Error resize(size_t size, bool preserveData) = 0; virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0; @@ -120,20 +139,57 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } - - bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) override; + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; gl::Error resize(size_t size, bool preserveData) override; uint8_t *map(size_t offset, size_t length, GLbitfield access) override; void unmap() override; private: - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); + static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + Renderer11 *renderer, + BufferUsage usage, + unsigned int bufferSize); ID3D11Buffer *mNativeStorage; }; +// A emulated indexed buffer storage represents an underlying D3D11 buffer for data +// that has been expanded to match the indices list used. This storage is only +// used for FL9_3 pointsprite rendering emulation. +class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage +{ + public: + EmulatedIndexedStorage(Renderer11 *renderer); + ~EmulatedIndexedStorage() override; + + bool isMappable() const override { return true; } + + ID3D11Buffer *getNativeStorage(); + + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + + gl::Error resize(size_t size, bool preserveData) override; + + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; + bool update(SourceIndexData *indexInfo, const TranslatedAttribute *attribute); + + private: + ID3D11Buffer *mNativeStorage; // contains expanded data for use by D3D + MemoryBuffer mMemoryBuffer; // original data (not expanded) + MemoryBuffer mIndicesMemoryBuffer; // indices data + SourceIndexData mIndexInfo; // indices information + size_t mAttributeStride; // per element stride in bytes + size_t mAttributeOffset; // starting offset +}; + // Pack storage represents internal storage for pack buffers. We implement pack buffers // as CPU memory, tied to a staging texture, for asynchronous texture readback. class Buffer11::PackStorage : public Buffer11::BufferStorage @@ -143,24 +199,24 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage ~PackStorage() override; bool isMappable() const override { return true; } - - bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) override; + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; gl::Error resize(size_t size, bool preserveData) override; uint8_t *map(size_t offset, size_t length, GLbitfield access) override; void unmap() override; - gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms); private: gl::Error flushQueuedPackCommand(); - ID3D11Texture2D *mStagingTexture; - DXGI_FORMAT mTextureFormat; - gl::Extents mTextureSize; + TextureHelper11 mStagingTexture; MemoryBuffer mMemoryBuffer; - PackPixelsParams *mQueuedPackCommand; + std::unique_ptr<PackPixelsParams> mQueuedPackCommand; PackPixelsParams mPackParams; bool mDataModified; }; @@ -175,9 +231,10 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage ~SystemMemoryStorage() override {} bool isMappable() const override { return true; } - - bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) override; + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; gl::Error resize(size_t size, bool preserveData) override; uint8_t *map(size_t offset, size_t length, GLbitfield access) override; @@ -193,23 +250,27 @@ Buffer11::Buffer11(Renderer11 *renderer) : BufferD3D(renderer), mRenderer(renderer), mSize(0), - mMappedStorage(NULL), - mReadUsageCount(0), - mHasSystemMemoryStorage(false) -{} + mMappedStorage(nullptr), + mBufferStorages(BUFFER_USAGE_COUNT, nullptr), + mConstantBufferStorageAdditionalSize(0), + mMaxConstantBufferLruCount(0), + mReadUsageCount(0) +{ +} Buffer11::~Buffer11() { - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + for (auto &storage : mBufferStorages) { - SafeDelete(it->second); + SafeDelete(storage); } -} -Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); - return static_cast<Buffer11*>(buffer); + for (auto &p : mConstantBufferRangeStoragesCache) + { + SafeDelete(p.second.storage); + } + + mRenderer->onBufferDelete(this); } gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) @@ -220,18 +281,14 @@ gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) return error; } - if (usage == GL_STATIC_DRAW) - { - initializeStaticData(); - } - + updateD3DBufferUsage(usage); return error; } gl::Error Buffer11::getData(const uint8_t **outData) { SystemMemoryStorage *systemMemoryStorage = nullptr; - gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); + gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); if (error.isError()) { @@ -310,15 +367,18 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) } mSize = std::max(mSize, requiredSize); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +gl::Error Buffer11::copySubData(BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) { - Buffer11 *sourceBuffer = makeBuffer11(source); - ASSERT(sourceBuffer != NULL); + Buffer11 *sourceBuffer = GetAs<Buffer11>(source); + ASSERT(sourceBuffer != nullptr); BufferStorage *copyDest = getLatestBufferStorage(); if (!copyDest) @@ -363,19 +423,26 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint copyDest->setDataRevision(copyDest->getDataRevision() + 1); mSize = std::max<size_t>(mSize, destOffset + size); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr) +{ + // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield + // and call mapRange. + ASSERT(access == GL_WRITE_ONLY_OES); + return mapRange(0, mSize, GL_MAP_WRITE_BIT, mapPtr); +} + +gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) { ASSERT(!mMappedStorage); BufferStorage *latestStorage = getLatestBufferStorage(); - if (latestStorage && - (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || - latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) { // Latest storage is mappable. mMappedStorage = latestStorage; @@ -396,6 +463,7 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid { // Update the data revision immediately, since the data might be changed at any time mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); } uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); @@ -408,24 +476,29 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::unmap() +gl::Error Buffer11::unmap(GLboolean *result) { ASSERT(mMappedStorage); mMappedStorage->unmap(); - mMappedStorage = NULL; + mMappedStorage = nullptr; + + // TODO: detect if we had corruption. if so, return false. + *result = GL_TRUE; + return gl::Error(GL_NO_ERROR); } void Buffer11::markTransformFeedbackUsage() { - BufferStorage *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + BufferStorage *transformFeedbackStorage = + getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); if (transformFeedbackStorage) { transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); } - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); } void Buffer11::markBufferUsage() @@ -435,14 +508,13 @@ void Buffer11::markBufferUsage() // Free the system memory storage if we decide it isn't being used very often. const unsigned int usageLimit = 5; - if (mReadUsageCount > usageLimit && mHasSystemMemoryStorage) + BufferStorage *&sysMemUsage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; + if (mReadUsageCount > usageLimit && sysMemUsage != nullptr) { - auto systemMemoryStorageIt = mBufferStorages.find(BUFFER_USAGE_SYSTEM_MEMORY); - ASSERT(systemMemoryStorageIt != mBufferStorages.end()); - - SafeDelete(systemMemoryStorageIt->second); - mBufferStorages.erase(systemMemoryStorageIt); - mHasSystemMemoryStorage = false; + if (getLatestBufferStorage() != sysMemUsage) + { + SafeDelete(sysMemUsage); + } } } @@ -455,12 +527,59 @@ ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) if (!bufferStorage) { // Storage out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, bufferStorage)); + return GetAs<NativeStorage>(bufferStorage)->getNativeStorage(); +} + +ID3D11Buffer *Buffer11::getEmulatedIndexedBuffer(SourceIndexData *indexInfo, + const TranslatedAttribute *attribute) +{ + markBufferUsage(); + + assert(indexInfo != nullptr); + assert(attribute != nullptr); - return static_cast<NativeStorage*>(bufferStorage)->getNativeStorage(); + BufferStorage *bufferStorage = getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX); + if (!bufferStorage) + { + // Storage out-of-memory + return nullptr; + } + + EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(bufferStorage); + if (!emulatedStorage->update(indexInfo, attribute)) + { + // Storage out-of-memory + return nullptr; + } + + return emulatedStorage->getNativeStorage(); +} + +ID3D11Buffer *Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size) +{ + markBufferUsage(); + + BufferStorage *bufferStorage; + + if (offset == 0) + { + bufferStorage = getBufferStorage(BUFFER_USAGE_UNIFORM); + } + else + { + bufferStorage = getConstantBufferRangeStorage(offset, size); + } + + if (!bufferStorage) + { + // Storage out-of-memory + return nullptr; + } + + return GetAs<NativeStorage>(bufferStorage)->getNativeStorage(); } ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) @@ -470,11 +589,10 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) if (!storage) { // Storage out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, storage)); - ID3D11Buffer *buffer = static_cast<NativeStorage*>(storage)->getNativeStorage(); + ID3D11Buffer *buffer = GetAs<NativeStorage>(storage)->getNativeStorage(); auto bufferSRVIt = mBufferResourceViews.find(srvFormat); @@ -491,16 +609,17 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) } } - ID3D11Device *device = mRenderer->getDevice(); - ID3D11ShaderResourceView *bufferSRV = NULL; + ID3D11Device *device = mRenderer->getDevice(); + ID3D11ShaderResourceView *bufferSRV = nullptr; const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; bufferSRVDesc.Buffer.ElementOffset = 0; - bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes; - bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - bufferSRVDesc.Format = srvFormat; + 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); @@ -511,14 +630,15 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) return bufferSRV; } -gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms) { - PackStorage *packStorage = getPackStorage(); + PackStorage *packStorage = getPackStorage(); BufferStorage *latestStorage = getLatestBufferStorage(); if (packStorage) { - gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params); + gl::Error error = packStorage->packPixels(readAttachment, params); if (error.isError()) { return error; @@ -529,14 +649,23 @@ gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, return gl::Error(GL_NO_ERROR); } +size_t Buffer11::getTotalCPUBufferMemoryBytes() const +{ + size_t allocationSize = 0; + + BufferStorage *staging = mBufferStorages[BUFFER_USAGE_STAGING]; + allocationSize += staging ? staging->getSize() : 0; + + BufferStorage *sysMem = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; + allocationSize += sysMem ? sysMem->getSize() : 0; + + return allocationSize; +} + Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) { - BufferStorage *newStorage = NULL; - auto directBufferIt = mBufferStorages.find(usage); - if (directBufferIt != mBufferStorages.end()) - { - newStorage = directBufferIt->second; - } + ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT); + BufferStorage *&newStorage = mBufferStorages[usage]; if (!newStorage) { @@ -547,15 +676,16 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) else if (usage == BUFFER_USAGE_SYSTEM_MEMORY) { newStorage = new SystemMemoryStorage(mRenderer); - mHasSystemMemoryStorage = true; + } + else if (usage == BUFFER_USAGE_EMULATED_INDEXED_VERTEX) + { + newStorage = new EmulatedIndexedStorage(mRenderer); } else { // buffer is not allocated, create it newStorage = new NativeStorage(mRenderer, usage); } - - mBufferStorages.insert(std::make_pair(usage, newStorage)); } // resize buffer @@ -564,19 +694,88 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) if (newStorage->resize(mSize, true).isError()) { // Out of memory error - return NULL; + return nullptr; + } + } + + updateBufferStorage(newStorage, 0, mSize); + + return newStorage; +} + +Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size) +{ + BufferStorage *newStorage; + + { + // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if + // we need to reclaim some space. + ConstantBufferCacheEntry *cacheEntry = &mConstantBufferRangeStoragesCache[offset]; + + if (!cacheEntry->storage) + { + cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM); + cacheEntry->lruCount = ++mMaxConstantBufferLruCount; } + + cacheEntry->lruCount = ++mMaxConstantBufferLruCount; + newStorage = cacheEntry->storage; } + if (newStorage->getSize() < static_cast<size_t>(size)) + { + size_t maximumAllowedAdditionalSize = 2 * getSize(); + + size_t sizeDelta = size - newStorage->getSize(); + + while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize) + { + auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache), + std::end(mConstantBufferRangeStoragesCache), + [](const ConstantBufferCache::value_type &a, + const ConstantBufferCache::value_type &b) + { + return a.second.lruCount < b.second.lruCount; + }); + + ASSERT(iter->second.storage != newStorage); + ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize()); + + mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize(); + SafeDelete(iter->second.storage); + mConstantBufferRangeStoragesCache.erase(iter); + } + + if (newStorage->resize(size, false).isError()) + { + // Out of memory error + return nullptr; + } + + mConstantBufferStorageAdditionalSize += sizeDelta; + + // We don't copy the old data when resizing the constant buffer because the data may be + // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the + // copy. + newStorage->setDataRevision(0); + } + + updateBufferStorage(newStorage, offset, size); + + return newStorage; +} + +void Buffer11::updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize) +{ BufferStorage *latestBuffer = getLatestBufferStorage(); - if (latestBuffer && latestBuffer->getDataRevision() > newStorage->getDataRevision()) + if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision()) { // Copy through a staging buffer if we're copying from or to a non-staging, mappable // buffer storage. This is because we can't map a GPU buffer, and copy CPU // data directly. If we're already using a staging buffer we're fine. if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING && - newStorage->getUsage() != BUFFER_USAGE_STAGING && - (!latestBuffer->isMappable() || !newStorage->isMappable())) + storage->getUsage() != BUFFER_USAGE_STAGING && + (!latestBuffer->isMappable() || !storage->isMappable())) { NativeStorage *stagingBuffer = getStagingStorage(); @@ -588,28 +787,25 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) // if copyFromStorage returns true, the D3D buffer has been recreated // and we should update our serial - if (newStorage->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) + if (storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0)) { updateSerial(); } - newStorage->setDataRevision(latestBuffer->getDataRevision()); + storage->setDataRevision(latestBuffer->getDataRevision()); } - - return newStorage; } Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const { // Even though we iterate over all the direct buffers, it is expected that only // 1 or 2 will be present. - BufferStorage *latestStorage = NULL; + BufferStorage *latestStorage = nullptr; DataRevision latestRevision = 0; - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + for (auto &storage : mBufferStorages) { - BufferStorage *storage = it->second; - if (!latestStorage || storage->getDataRevision() > latestRevision) + if (storage && (!latestStorage || storage->getDataRevision() > latestRevision)) { - latestStorage = storage; + latestStorage = storage; latestRevision = storage->getDataRevision(); } } @@ -620,7 +816,7 @@ Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const if (latestStorage->resize(mSize, true).isError()) { // Out of memory error - return NULL; + return nullptr; } } @@ -634,11 +830,10 @@ Buffer11::NativeStorage *Buffer11::getStagingStorage() if (!stagingStorage) { // Out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, stagingStorage)); - return static_cast<NativeStorage*>(stagingStorage); + return GetAs<NativeStorage>(stagingStorage); } Buffer11::PackStorage *Buffer11::getPackStorage() @@ -648,11 +843,10 @@ Buffer11::PackStorage *Buffer11::getPackStorage() if (!packStorage) { // Out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(PackStorage*, packStorage)); - return static_cast<PackStorage*>(packStorage); + return GetAs<PackStorage>(packStorage); } bool Buffer11::supportsDirectBinding() const @@ -664,10 +858,7 @@ bool Buffer11::supportsDirectBinding() const } Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) - : mRenderer(renderer), - mUsage(usage), - mRevision(0), - mBufferSize(0) + : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) { } @@ -689,8 +880,7 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s } Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) - : BufferStorage(renderer, usage), - mNativeStorage(NULL) + : BufferStorage(renderer, usage), mNativeStorage(nullptr) { } @@ -700,19 +890,21 @@ Buffer11::NativeStorage::~NativeStorage() } // Returns true if it recreates the direct buffer -bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - size_t requiredSize = sourceOffset + size; - bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; + size_t requiredSize = destOffset + size; + bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; // (Re)initialize D3D buffer if needed if (createBuffer) { bool preserveData = (destOffset > 0); - resize(source->getSize(), preserveData); + resize(requiredSize, preserveData); } if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK || @@ -724,8 +916,12 @@ bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sour D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource); - UNUSED_ASSERTION_VARIABLE(hr); ASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + { + source->unmap(); + return false; + } uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset; @@ -738,20 +934,18 @@ bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sour } else { - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); - D3D11_BOX srcBox; - srcBox.left = sourceOffset; - srcBox.right = sourceOffset + size; - srcBox.top = 0; + srcBox.left = static_cast<unsigned int>(sourceOffset); + srcBox.right = static_cast<unsigned int>(sourceOffset + size); + srcBox.top = 0; srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; + srcBox.front = 0; + srcBox.back = 1; - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); - ID3D11Buffer *sourceBuffer = static_cast<NativeStorage*>(source)->getNativeStorage(); + ID3D11Buffer *sourceBuffer = GetAs<NativeStorage>(source)->getNativeStorage(); - context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); + context->CopySubresourceRegion(mNativeStorage, 0, static_cast<unsigned int>(destOffset), 0, + 0, sourceBuffer, 0, &srcBox); } return createBuffer; @@ -759,32 +953,35 @@ bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sour gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) { - ID3D11Device *device = mRenderer->getDevice(); + ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); D3D11_BUFFER_DESC bufferDesc; - fillBufferDesc(&bufferDesc, mRenderer, mUsage, size); + fillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size)); ID3D11Buffer *newBuffer; - HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", + result); } + d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage"); + if (mNativeStorage && preserveData) { // We don't call resize if the buffer is big enough already. ASSERT(mBufferSize <= size); D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = mBufferSize; - srcBox.top = 0; + srcBox.left = 0; + srcBox.right = static_cast<unsigned int>(mBufferSize); + srcBox.top = 0; srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; + srcBox.front = 0; + srcBox.back = 1; context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); } @@ -798,58 +995,62 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) return gl::Error(GL_NO_ERROR); } -void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, - BufferUsage usage, unsigned int bufferSize) +void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + Renderer11 *renderer, + BufferUsage usage, + unsigned int bufferSize) { - bufferDesc->ByteWidth = bufferSize; - bufferDesc->MiscFlags = 0; + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; bufferDesc->StructureByteStride = 0; switch (usage) { - case BUFFER_USAGE_STAGING: - bufferDesc->Usage = D3D11_USAGE_STAGING; - bufferDesc->BindFlags = 0; - bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - break; + case BUFFER_USAGE_STAGING: + bufferDesc->Usage = D3D11_USAGE_STAGING; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; - case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - if (renderer->isES3Capable()) - { - bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; - } + if (renderer->isES3Capable()) + { + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + } - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_INDEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_PIXEL_UNPACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_UNIFORM: - bufferDesc->Usage = D3D11_USAGE_DYNAMIC; - bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; - bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - - // 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); - bufferDesc->ByteWidth = std::min<UINT>(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); - break; - - default: - UNREACHABLE(); + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_PIXEL_UNPACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_UNIFORM: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + // 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); + bufferDesc->ByteWidth = + std::min<UINT>(bufferDesc->ByteWidth, + static_cast<UINT>(renderer->getRendererCaps().maxUniformBlockSize)); + break; + + default: + UNREACHABLE(); } } @@ -859,14 +1060,16 @@ uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield a D3D11_MAPPED_SUBRESOURCE mappedResource; ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); - UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + 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); - UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); - - return static_cast<uint8_t*>(mappedResource.pData) + offset; + if (FAILED(result)) + { + return nullptr; + } + return static_cast<uint8_t *>(mappedResource.pData) + offset; } void Buffer11::NativeStorage::unmap() @@ -876,23 +1079,189 @@ void Buffer11::NativeStorage::unmap() context->Unmap(mNativeStorage, 0); } +Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer) + : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr) +{ +} + +Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() +{ + SafeRelease(mNativeStorage); +} + +ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() +{ + if (!mNativeStorage) + { + // Expand the memory storage upon request and cache the results. + unsigned int expandedDataSize = + static_cast<unsigned int>((mIndexInfo.srcCount * mAttributeStride) + mAttributeOffset); + MemoryBuffer expandedData; + if (!expandedData.resize(expandedDataSize)) + { + return nullptr; + } + + // Clear the contents of the allocated buffer + ZeroMemory(expandedData.data(), expandedDataSize); + + uint8_t *curr = expandedData.data(); + const uint8_t *ptr = static_cast<const uint8_t *>(mIndexInfo.srcIndices); + + // Ensure that we start in the correct place for the emulated data copy operation to + // maintain offset behaviors. + curr += mAttributeOffset; + + ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>; + + switch (mIndexInfo.srcIndexType) + { + case GL_UNSIGNED_INT: + readIndexValue = ReadIndexValueFromIndices<GLuint>; + break; + case GL_UNSIGNED_SHORT: + readIndexValue = ReadIndexValueFromIndices<GLushort>; + break; + case GL_UNSIGNED_BYTE: + readIndexValue = ReadIndexValueFromIndices<GLubyte>; + break; + } + + // Iterate over the cached index data and copy entries indicated into the emulated buffer. + for (GLuint i = 0; i < mIndexInfo.srcCount; i++) + { + GLuint idx = readIndexValue(ptr, i); + memcpy(curr, mMemoryBuffer.data() + (mAttributeStride * idx), mAttributeStride); + curr += mAttributeStride; + } + + // Finally, initialize the emulated indexed native storage object with the newly copied data + // and free the temporary buffers used. + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = expandedDataSize; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + + D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0}; + + HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage); + if (FAILED(result)) + { + ERR("Could not create emulated index data buffer: %08lX", result); + return nullptr; + } + d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage"); + } + + return mNativeStorage; +} + +bool Buffer11::EmulatedIndexedStorage::update(SourceIndexData *indexInfo, + const TranslatedAttribute *attribute) +{ + // If a change in the indices applied from the last draw call is detected, then the emulated + // indexed buffer needs to be invalidated. After invalidation, the change detected flag should + // be cleared to avoid unnecessary recreation of the buffer. + if (mNativeStorage == nullptr || indexInfo->srcIndicesChanged) + { + SafeRelease(mNativeStorage); + + // Copy attribute offset and stride information + mAttributeStride = attribute->stride; + mAttributeOffset = attribute->offset; + + // Copy the source index data. This ensures that the lifetime of the indices pointer + // stays with this storage until the next time we invalidate. + size_t indicesDataSize = 0; + switch (indexInfo->srcIndexType) + { + case GL_UNSIGNED_INT: + indicesDataSize = sizeof(GLuint) * indexInfo->srcCount; + break; + case GL_UNSIGNED_SHORT: + indicesDataSize = sizeof(GLushort) * indexInfo->srcCount; + break; + case GL_UNSIGNED_BYTE: + indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount; + break; + default: + indicesDataSize = sizeof(GLushort) * indexInfo->srcCount; + break; + } + + if (!mIndicesMemoryBuffer.resize(indicesDataSize)) + { + return false; + } + + memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize); + + // Copy the source index data description and update the srcIndices pointer to point + // to our cached index data. + mIndexInfo = *indexInfo; + mIndexInfo.srcIndices = mIndicesMemoryBuffer.data(); + + indexInfo->srcIndicesChanged = false; + } + return true; +} + +bool Buffer11::EmulatedIndexedStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ + ASSERT(source->isMappable()); + const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); + ASSERT(destOffset + size <= mMemoryBuffer.size()); + memcpy(mMemoryBuffer.data() + destOffset, sourceData, size); + source->unmap(); + return true; +} + +gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData) +{ + if (mMemoryBuffer.size() < size) + { + if (!mMemoryBuffer.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage"); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +uint8_t *Buffer11::EmulatedIndexedStorage::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size()); + return mMemoryBuffer.data() + offset; +} + +void Buffer11::EmulatedIndexedStorage::unmap() +{ + // No-op +} + Buffer11::PackStorage::PackStorage(Renderer11 *renderer) - : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), - mStagingTexture(NULL), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mQueuedPackCommand(NULL), - mDataModified(false) + : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false) { } Buffer11::PackStorage::~PackStorage() { - SafeRelease(mStagingTexture); - SafeDelete(mQueuedPackCommand); } -bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { // We copy through a staging buffer when drawing with a pack buffer, // or for other cases where we access the pack buffer @@ -925,7 +1294,7 @@ uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield acc gl::Error error = flushQueuedPackCommand(); if (error.isError()) { - return NULL; + return nullptr; } mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); @@ -938,7 +1307,8 @@ void Buffer11::PackStorage::unmap() // No-op } -gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms) { gl::Error error = flushQueuedPackCommand(); if (error.isError()) @@ -946,54 +1316,37 @@ gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT src return error; } - mQueuedPackCommand = new PackPixelsParams(params); - - D3D11_TEXTURE2D_DESC textureDesc; - srcTexure->GetDesc(&textureDesc); - - if (mStagingTexture != NULL && - (mTextureFormat != textureDesc.Format || - mTextureSize.width != params.area.width || - mTextureSize.height != params.area.height)) + RenderTarget11 *renderTarget = nullptr; + error = readAttachment.getRenderTarget(&renderTarget); + if (error.isError()) { - SafeRelease(mStagingTexture); - mTextureSize.width = 0; - mTextureSize.height = 0; - mTextureFormat = DXGI_FORMAT_UNKNOWN; + return error; } - if (mStagingTexture == NULL) + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + ASSERT(renderTargetResource); + + unsigned int srcSubresource = renderTarget->getSubresourceIndex(); + TextureHelper11 srcTexture = TextureHelper11::MakeAndReference(renderTargetResource); + + mQueuedPackCommand.reset(new PackPixelsParams(params)); + + gl::Extents srcTextureSize(params.area.width, params.area.height, 1); + if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() || + mStagingTexture.getExtents() != srcTextureSize) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT hr; - - mTextureSize.width = params.area.width; - mTextureSize.height = params.area.height; - mTextureFormat = textureDesc.Format; - - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = params.area.width; - stagingDesc.Height = params.area.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = mTextureFormat; - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.MiscFlags = 0; - - hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); - if (FAILED(hr)) + auto textureOrError = + CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormat(), + srcTextureSize, mRenderer->getDevice()); + if (textureOrError.isError()) { - ASSERT(hr == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture."); + return textureOrError.getError(); } + mStagingTexture = std::move(textureOrError.getResult()); } // ReadPixels from multisampled FBOs isn't supported in current GL - ASSERT(textureDesc.SampleDesc.Count <= 1); + ASSERT(srcTexture.getSampleCount() <= 1); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); D3D11_BOX srcBox; @@ -1001,11 +1354,18 @@ gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT src srcBox.right = params.area.x + params.area.width; srcBox.top = params.area.y; srcBox.bottom = params.area.y + params.area.height; - srcBox.front = 0; - srcBox.back = 1; + + // Select the correct layer from a 3D attachment + srcBox.front = 0; + if (mStagingTexture.getTextureType() == GL_TEXTURE_3D) + { + srcBox.front = static_cast<UINT>(readAttachment.layer()); + } + srcBox.back = srcBox.front + 1; // Asynchronous copy - immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); + immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0, + srcTexture.getResource(), srcSubresource, &srcBox); return gl::Error(GL_NO_ERROR); } @@ -1016,8 +1376,9 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() if (mQueuedPackCommand) { - gl::Error error = mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); - SafeDelete(mQueuedPackCommand); + gl::Error error = + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + mQueuedPackCommand.reset(nullptr); if (error.isError()) { return error; @@ -1029,10 +1390,13 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) -{} +{ +} -bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { ASSERT(source->isMappable()); const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); @@ -1066,5 +1430,4 @@ void Buffer11::SystemMemoryStorage::unmap() { // No-op } - } |