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