1 // 2 // Copyright 2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. 8 9 #ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ 10 #define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ 11 12 #include <array> 13 #include <map> 14 15 #include "libANGLE/angletypes.h" 16 #include "libANGLE/renderer/d3d/BufferD3D.h" 17 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 18 19 namespace gl 20 { 21 class FramebufferAttachment; 22 } 23 24 namespace rx 25 { 26 struct PackPixelsParams; 27 class Renderer11; 28 struct SourceIndexData; 29 struct TranslatedAttribute; 30 31 // The order of this enum governs priority of 'getLatestBufferStorage'. 32 enum BufferUsage 33 { 34 BUFFER_USAGE_STAGING, 35 BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, 36 BUFFER_USAGE_INDEX, 37 // TODO: possibly share this buffer type with shader storage buffers. 38 BUFFER_USAGE_INDIRECT, 39 BUFFER_USAGE_PIXEL_UNPACK, 40 BUFFER_USAGE_PIXEL_PACK, 41 BUFFER_USAGE_UNIFORM, 42 BUFFER_USAGE_SYSTEM_MEMORY, 43 BUFFER_USAGE_EMULATED_INDEXED_VERTEX, 44 45 BUFFER_USAGE_COUNT, 46 }; 47 48 typedef size_t DataRevision; 49 50 class Buffer11 : public BufferD3D 51 { 52 public: 53 Buffer11(const gl::BufferState &state, Renderer11 *renderer); 54 ~Buffer11() override; 55 56 gl::ErrorOrResult<ID3D11Buffer *> getBuffer(const gl::Context *context, BufferUsage usage); 57 gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(const gl::Context *context, 58 SourceIndexData *indexInfo, 59 const TranslatedAttribute &attribute, 60 GLint startVertex); 61 gl::Error getConstantBufferRange(const gl::Context *context, 62 GLintptr offset, 63 GLsizeiptr size, 64 const d3d11::Buffer **bufferOut, 65 UINT *firstConstantOut, 66 UINT *numConstantsOut); 67 gl::ErrorOrResult<const d3d11::ShaderResourceView *> getSRV(const gl::Context *context, 68 DXGI_FORMAT srvFormat); isMapped()69 bool isMapped() const { return mMappedStorage != nullptr; } 70 gl::Error packPixels(const gl::Context *context, 71 const gl::FramebufferAttachment &readAttachment, 72 const PackPixelsParams ¶ms); 73 size_t getTotalCPUBufferMemoryBytes() const; 74 75 // BufferD3D implementation 76 size_t getSize() const override; 77 bool supportsDirectBinding() const override; 78 gl::Error getData(const gl::Context *context, const uint8_t **outData) override; 79 void initializeStaticData(const gl::Context *context) override; 80 void invalidateStaticData(const gl::Context *context) override; 81 82 // BufferImpl implementation 83 gl::Error setData(const gl::Context *context, 84 gl::BufferBinding target, 85 const void *data, 86 size_t size, 87 gl::BufferUsage usage) override; 88 gl::Error setSubData(const gl::Context *context, 89 gl::BufferBinding target, 90 const void *data, 91 size_t size, 92 size_t offset) override; 93 gl::Error copySubData(const gl::Context *context, 94 BufferImpl *source, 95 GLintptr sourceOffset, 96 GLintptr destOffset, 97 GLsizeiptr size) override; 98 gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) override; 99 gl::Error mapRange(const gl::Context *context, 100 size_t offset, 101 size_t length, 102 GLbitfield access, 103 void **mapPtr) override; 104 gl::Error unmap(const gl::Context *context, GLboolean *result) override; 105 gl::Error markTransformFeedbackUsage(const gl::Context *context) override; 106 107 // We use two set of dirty events. Static buffers are marked dirty whenever 108 // data changes, because they must be re-translated. Direct buffers only need to be 109 // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often. 110 OnBufferDataDirtyChannel *getStaticBroadcastChannel(); 111 OnBufferDataDirtyChannel *getDirectBroadcastChannel(); 112 113 private: 114 class BufferStorage; 115 class EmulatedIndexedStorage; 116 class NativeStorage; 117 class PackStorage; 118 class SystemMemoryStorage; 119 120 struct ConstantBufferCacheEntry 121 { ConstantBufferCacheEntryConstantBufferCacheEntry122 ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) {} 123 124 BufferStorage *storage; 125 unsigned int lruCount; 126 }; 127 128 void markBufferUsage(BufferUsage usage); 129 gl::Error garbageCollection(const gl::Context *context, BufferUsage currentUsage); 130 gl::ErrorOrResult<NativeStorage *> getStagingStorage(const gl::Context *context); 131 gl::ErrorOrResult<PackStorage *> getPackStorage(const gl::Context *context); 132 gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage(const gl::Context *context); 133 134 gl::Error updateBufferStorage(const gl::Context *context, 135 BufferStorage *storage, 136 size_t sourceOffset, 137 size_t storageSize); 138 gl::ErrorOrResult<BufferStorage *> getBufferStorage(const gl::Context *context, 139 BufferUsage usage); 140 gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage(const gl::Context *context) const; 141 142 gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(const gl::Context *context, 143 GLintptr offset, 144 GLsizeiptr size); 145 146 BufferStorage *allocateStorage(BufferUsage usage); 147 void updateDeallocThreshold(BufferUsage usage); 148 149 // Free the storage if we decide it isn't being used very often. 150 gl::Error checkForDeallocation(const gl::Context *context, BufferUsage usage); 151 152 // For some cases of uniform buffer storage, we can't deallocate system memory storage. 153 bool canDeallocateSystemMemory() const; 154 155 // Updates data revisions and latest storage. 156 void onCopyStorage(BufferStorage *dest, BufferStorage *source); 157 void onStorageUpdate(BufferStorage *updatedStorage); 158 159 Renderer11 *mRenderer; 160 size_t mSize; 161 162 BufferStorage *mMappedStorage; 163 164 // Buffer storages are sorted by usage. It's important that the latest buffer storage picks 165 // the lowest usage in the case where two storages are tied on data revision - this ensures 166 // we never do anything dangerous like map a uniform buffer over a staging or system memory 167 // copy. 168 std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages; 169 BufferStorage *mLatestBufferStorage; 170 171 // These two arrays are used to track when to free unused storage. 172 std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds; 173 std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness; 174 175 // Cache of D3D11 constant buffer for specific ranges of buffer data. 176 // This is used to emulate UBO ranges on 11.0 devices. 177 // Constant buffers are indexed by there start offset. 178 typedef std::map<GLintptr /*offset*/, ConstantBufferCacheEntry> ConstantBufferCache; 179 ConstantBufferCache mConstantBufferRangeStoragesCache; 180 size_t mConstantBufferStorageAdditionalSize; 181 unsigned int mMaxConstantBufferLruCount; 182 183 OnBufferDataDirtyChannel mStaticBroadcastChannel; 184 OnBufferDataDirtyChannel mDirectBroadcastChannel; 185 }; 186 187 } // namespace rx 188 189 #endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ 190