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 &params);
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