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_SYSTEM_MEMORY, 35 BUFFER_USAGE_STAGING, 36 BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, 37 BUFFER_USAGE_INDEX, 38 BUFFER_USAGE_INDIRECT, 39 BUFFER_USAGE_PIXEL_UNPACK, 40 BUFFER_USAGE_PIXEL_PACK, 41 BUFFER_USAGE_UNIFORM, 42 BUFFER_USAGE_STRUCTURED, 43 BUFFER_USAGE_EMULATED_INDEXED_VERTEX, 44 BUFFER_USAGE_RAW_UAV, 45 46 BUFFER_USAGE_COUNT, 47 }; 48 49 typedef size_t DataRevision; 50 51 class Buffer11 : public BufferD3D 52 { 53 public: 54 Buffer11(const gl::BufferState &state, Renderer11 *renderer); 55 ~Buffer11() override; 56 57 angle::Result getBuffer(const gl::Context *context, 58 BufferUsage usage, 59 ID3D11Buffer **bufferOut); 60 angle::Result getEmulatedIndexedBuffer(const gl::Context *context, 61 SourceIndexData *indexInfo, 62 const TranslatedAttribute &attribute, 63 GLint startVertex, 64 ID3D11Buffer **bufferOut); 65 angle::Result getConstantBufferRange(const gl::Context *context, 66 GLintptr offset, 67 GLsizeiptr size, 68 const d3d11::Buffer **bufferOut, 69 UINT *firstConstantOut, 70 UINT *numConstantsOut); 71 angle::Result getStructuredBufferRangeSRV(const gl::Context *context, 72 unsigned int offset, 73 unsigned int size, 74 unsigned int structureByteStride, 75 const d3d11::ShaderResourceView **srvOut); 76 angle::Result getSRV(const gl::Context *context, 77 DXGI_FORMAT srvFormat, 78 const d3d11::ShaderResourceView **srvOut); 79 angle::Result getRawUAVRange(const gl::Context *context, 80 GLintptr offset, 81 GLsizeiptr size, 82 d3d11::UnorderedAccessView **uavOut); 83 84 angle::Result markRawBufferUsage(const gl::Context *context); isMapped()85 bool isMapped() const { return mMappedStorage != nullptr; } 86 angle::Result packPixels(const gl::Context *context, 87 const gl::FramebufferAttachment &readAttachment, 88 const PackPixelsParams ¶ms); 89 size_t getTotalCPUBufferMemoryBytes() const; 90 91 // BufferD3D implementation 92 size_t getSize() const override; 93 bool supportsDirectBinding() const override; 94 angle::Result getData(const gl::Context *context, const uint8_t **outData) override; 95 void initializeStaticData(const gl::Context *context) override; 96 void invalidateStaticData(const gl::Context *context) override; 97 98 // BufferImpl implementation 99 angle::Result setData(const gl::Context *context, 100 gl::BufferBinding target, 101 const void *data, 102 size_t size, 103 gl::BufferUsage usage) override; 104 angle::Result setSubData(const gl::Context *context, 105 gl::BufferBinding target, 106 const void *data, 107 size_t size, 108 size_t offset) override; 109 angle::Result copySubData(const gl::Context *context, 110 BufferImpl *source, 111 GLintptr sourceOffset, 112 GLintptr destOffset, 113 GLsizeiptr size) override; 114 angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override; 115 angle::Result mapRange(const gl::Context *context, 116 size_t offset, 117 size_t length, 118 GLbitfield access, 119 void **mapPtr) override; 120 angle::Result unmap(const gl::Context *context, GLboolean *result) override; 121 angle::Result markTransformFeedbackUsage(const gl::Context *context) override; 122 123 private: 124 class BufferStorage; 125 class EmulatedIndexedStorage; 126 class NativeStorage; 127 class PackStorage; 128 class SystemMemoryStorage; 129 class StructuredBufferStorage; 130 131 struct BufferCacheEntry 132 { BufferCacheEntryBufferCacheEntry133 BufferCacheEntry() : storage(nullptr), lruCount(0) {} 134 135 BufferStorage *storage; 136 unsigned int lruCount; 137 }; 138 139 struct StructuredBufferKey 140 { StructuredBufferKeyStructuredBufferKey141 StructuredBufferKey(unsigned int offsetIn, unsigned int structureByteStrideIn) 142 : offset(offsetIn), structureByteStride(structureByteStrideIn) 143 {} 144 bool operator<(const StructuredBufferKey &rhs) const 145 { 146 return std::tie(offset, structureByteStride) < 147 std::tie(rhs.offset, rhs.structureByteStride); 148 } 149 unsigned int offset; 150 unsigned int structureByteStride; 151 }; 152 153 void markBufferUsage(BufferUsage usage); 154 angle::Result markBufferUsage(const gl::Context *context, BufferUsage usage); 155 angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage); 156 157 angle::Result updateBufferStorage(const gl::Context *context, 158 BufferStorage *storage, 159 size_t sourceOffset, 160 size_t storageSize); 161 162 angle::Result getNativeStorageForUAV(const gl::Context *context, 163 Buffer11::NativeStorage **storageOut); 164 165 template <typename StorageOutT> 166 angle::Result getBufferStorage(const gl::Context *context, 167 BufferUsage usage, 168 StorageOutT **storageOut); 169 170 template <typename StorageOutT> 171 angle::Result getStagingStorage(const gl::Context *context, StorageOutT **storageOut); 172 173 angle::Result getLatestBufferStorage(const gl::Context *context, 174 BufferStorage **storageOut) const; 175 176 angle::Result getConstantBufferRangeStorage(const gl::Context *context, 177 GLintptr offset, 178 GLsizeiptr size, 179 NativeStorage **storageOut); 180 181 BufferStorage *allocateStorage(BufferUsage usage); 182 void updateDeallocThreshold(BufferUsage usage); 183 184 // Free the storage if we decide it isn't being used very often. 185 angle::Result checkForDeallocation(const gl::Context *context, BufferUsage usage); 186 187 // For some cases of uniform buffer storage, we can't deallocate system memory storage. 188 bool canDeallocateSystemMemory() const; 189 190 // Updates data revisions and latest storage. 191 void onCopyStorage(BufferStorage *dest, BufferStorage *source); 192 void onStorageUpdate(BufferStorage *updatedStorage); 193 194 Renderer11 *mRenderer; 195 size_t mSize; 196 197 BufferStorage *mMappedStorage; 198 199 // Buffer storages are sorted by usage. It's important that the latest buffer storage picks 200 // the lowest usage in the case where two storages are tied on data revision - this ensures 201 // we never do anything dangerous like map a uniform buffer over a staging or system memory 202 // copy. 203 std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages; 204 BufferStorage *mLatestBufferStorage; 205 206 // These two arrays are used to track when to free unused storage. 207 std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds; 208 std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness; 209 210 // Cache of D3D11 constant buffer for specific ranges of buffer data. 211 // This is used to emulate UBO ranges on 11.0 devices. 212 // Constant buffers are indexed by there start offset. 213 typedef std::map<GLintptr /*offset*/, BufferCacheEntry> BufferCache; 214 BufferCache mConstantBufferRangeStoragesCache; 215 size_t mConstantBufferStorageAdditionalSize; 216 unsigned int mMaxConstantBufferLruCount; 217 218 typedef std::map<StructuredBufferKey, BufferCacheEntry> StructuredBufferCache; 219 StructuredBufferCache mStructuredBufferRangeStoragesCache; 220 size_t mStructuredBufferStorageAdditionalSize; 221 unsigned int mMaxStructuredBufferLruCount; 222 }; 223 224 } // namespace rx 225 226 #endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ 227