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