• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &params);
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