• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // VertexArray11:
7 //   Implementation of rx::VertexArray11.
8 //
9 
10 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
11 
12 #include "common/bitset_utils.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/renderer/d3d/IndexBuffer.h"
15 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
16 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
17 
18 using namespace angle;
19 
20 namespace rx
21 {
VertexArray11(const gl::VertexArrayState & data)22 VertexArray11::VertexArray11(const gl::VertexArrayState &data)
23     : VertexArrayImpl(data),
24       mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE),
25       mTranslatedAttribs(data.getMaxAttribs()),
26       mAppliedNumViewsToDivisor(1),
27       mCurrentElementArrayStorage(IndexStorageType::Invalid),
28       mCachedDestinationIndexType(gl::DrawElementsType::InvalidEnum)
29 {}
30 
~VertexArray11()31 VertexArray11::~VertexArray11() {}
32 
destroy(const gl::Context * context)33 void VertexArray11::destroy(const gl::Context *context) {}
34 
35 // As VertexAttribPointer can modify both attribute and binding, we should also set other attributes
36 // that are also using this binding dirty.
37 #define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                                                \
38     case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                                        \
39         if ((*attribBits)[INDEX][gl::VertexArray::DirtyAttribBitType::DIRTY_ATTRIB_POINTER]) \
40         {                                                                                    \
41             attributesToUpdate |= mState.getBindingToAttributesMask(INDEX);                  \
42         }                                                                                    \
43         else                                                                                 \
44         {                                                                                    \
45             attributesToUpdate.set(INDEX);                                                   \
46         }                                                                                    \
47         invalidateVertexBuffer = true;                                                       \
48         (*attribBits)[INDEX].reset();                                                        \
49         break;
50 
51 #define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                          \
52     case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                  \
53         attributesToUpdate |= mState.getBindingToAttributesMask(INDEX); \
54         invalidateVertexBuffer = true;                                  \
55         (*bindingBits)[INDEX].reset();                                  \
56         break;
57 
58 #define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX)                      \
59     case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX:              \
60         if (mAttributeStorageTypes[INDEX] == VertexStorageType::STATIC) \
61         {                                                               \
62             invalidateVertexBuffer = true;                              \
63             mAttribsToTranslate.set(INDEX);                             \
64         }                                                               \
65         break;
66 
syncState(const gl::Context * context,const gl::VertexArray::DirtyBits & dirtyBits,gl::VertexArray::DirtyAttribBitsArray * attribBits,gl::VertexArray::DirtyBindingBitsArray * bindingBits)67 angle::Result VertexArray11::syncState(const gl::Context *context,
68                                        const gl::VertexArray::DirtyBits &dirtyBits,
69                                        gl::VertexArray::DirtyAttribBitsArray *attribBits,
70                                        gl::VertexArray::DirtyBindingBitsArray *bindingBits)
71 {
72     ASSERT(dirtyBits.any());
73 
74     Renderer11 *renderer         = GetImplAs<Context11>(context)->getRenderer();
75     StateManager11 *stateManager = renderer->getStateManager();
76 
77     // Generate a state serial. This serial is used in the program class to validate the cached
78     // input layout, and skip recomputation in the fast path.
79     mCurrentStateSerial = renderer->generateSerial();
80 
81     bool invalidateVertexBuffer = false;
82 
83     gl::AttributesMask attributesToUpdate;
84 
85     // Make sure we trigger re-translation for static index or vertex data.
86     for (size_t dirtyBit : dirtyBits)
87     {
88         switch (dirtyBit)
89         {
90             case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
91             case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
92             {
93                 mLastDrawElementsType.reset();
94                 mLastDrawElementsIndices.reset();
95                 mLastPrimitiveRestartEnabled.reset();
96                 mCachedIndexInfo.reset();
97                 break;
98             }
99 
100                 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)
101                 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC)
102                 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)
103 
104             default:
105                 UNREACHABLE();
106                 break;
107         }
108     }
109 
110     for (size_t attribIndex : attributesToUpdate)
111     {
112         updateVertexAttribStorage(context, stateManager, attribIndex);
113     }
114 
115     if (invalidateVertexBuffer)
116     {
117         // TODO(jmadill): Individual attribute invalidation.
118         stateManager->invalidateVertexBuffer();
119     }
120 
121     return angle::Result::Continue;
122 }
123 
syncStateForDraw(const gl::Context * context,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLsizei instances,GLint baseVertex)124 angle::Result VertexArray11::syncStateForDraw(const gl::Context *context,
125                                               GLint firstVertex,
126                                               GLsizei vertexOrIndexCount,
127                                               gl::DrawElementsType indexTypeOrInvalid,
128                                               const void *indices,
129                                               GLsizei instances,
130                                               GLint baseVertex)
131 {
132     Renderer11 *renderer         = GetImplAs<Context11>(context)->getRenderer();
133     StateManager11 *stateManager = renderer->getStateManager();
134 
135     const gl::State &glState   = context->getState();
136     const gl::Program *program = glState.getProgram();
137     ASSERT(program);
138     const gl::ProgramExecutable &executable = program->getExecutable();
139 
140     mAppliedNumViewsToDivisor = (program->usesMultiview() ? program->getNumViews() : 1);
141 
142     if (mAttribsToTranslate.any())
143     {
144         const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask();
145         gl::AttributesMask activeDirtyAttribs     = (mAttribsToTranslate & activeLocations);
146         if (activeDirtyAttribs.any())
147         {
148             ANGLE_TRY(updateDirtyAttribs(context, activeDirtyAttribs));
149             stateManager->invalidateInputLayout();
150         }
151     }
152 
153     if (mDynamicAttribsMask.any())
154     {
155         const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask();
156         gl::AttributesMask activeDynamicAttribs   = (mDynamicAttribsMask & activeLocations);
157 
158         if (activeDynamicAttribs.any())
159         {
160             ANGLE_TRY(updateDynamicAttribs(context, stateManager->getVertexDataManager(),
161                                            firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
162                                            indices, instances, baseVertex, activeDynamicAttribs));
163             stateManager->invalidateInputLayout();
164         }
165     }
166 
167     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
168     {
169         bool restartEnabled = context->getState().isPrimitiveRestartEnabled();
170         if (!mLastDrawElementsType.valid() || mLastDrawElementsType.value() != indexTypeOrInvalid ||
171             mLastDrawElementsIndices.value() != indices ||
172             mLastPrimitiveRestartEnabled.value() != restartEnabled)
173         {
174             mLastDrawElementsType        = indexTypeOrInvalid;
175             mLastDrawElementsIndices     = indices;
176             mLastPrimitiveRestartEnabled = restartEnabled;
177 
178             ANGLE_TRY(updateElementArrayStorage(context, vertexOrIndexCount, indexTypeOrInvalid,
179                                                 indices, restartEnabled));
180             stateManager->invalidateIndexBuffer();
181         }
182         else if (mCurrentElementArrayStorage == IndexStorageType::Dynamic)
183         {
184             stateManager->invalidateIndexBuffer();
185         }
186     }
187 
188     return angle::Result::Continue;
189 }
190 
updateElementArrayStorage(const gl::Context * context,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices,bool restartEnabled)191 angle::Result VertexArray11::updateElementArrayStorage(const gl::Context *context,
192                                                        GLsizei indexCount,
193                                                        gl::DrawElementsType indexType,
194                                                        const void *indices,
195                                                        bool restartEnabled)
196 {
197     bool usePrimitiveRestartWorkaround = UsePrimitiveRestartWorkaround(restartEnabled, indexType);
198 
199     ANGLE_TRY(GetIndexTranslationDestType(context, indexCount, indexType, indices,
200                                           usePrimitiveRestartWorkaround,
201                                           &mCachedDestinationIndexType));
202 
203     unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
204 
205     mCurrentElementArrayStorage =
206         ClassifyIndexStorage(context->getState(), mState.getElementArrayBuffer(), indexType,
207                              mCachedDestinationIndexType, offset);
208 
209     return angle::Result::Continue;
210 }
211 
updateVertexAttribStorage(const gl::Context * context,StateManager11 * stateManager,size_t attribIndex)212 void VertexArray11::updateVertexAttribStorage(const gl::Context *context,
213                                               StateManager11 *stateManager,
214                                               size_t attribIndex)
215 {
216     const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
217     const gl::VertexBinding &binding  = mState.getBindingFromAttribIndex(attribIndex);
218 
219     VertexStorageType newStorageType = ClassifyAttributeStorage(context, attrib, binding);
220 
221     // Note: having an unchanged storage type doesn't mean the attribute is clean.
222     mAttribsToTranslate.set(attribIndex, newStorageType != VertexStorageType::DYNAMIC);
223 
224     if (mAttributeStorageTypes[attribIndex] == newStorageType)
225         return;
226 
227     mAttributeStorageTypes[attribIndex] = newStorageType;
228     mDynamicAttribsMask.set(attribIndex, newStorageType == VertexStorageType::DYNAMIC);
229 
230     if (newStorageType == VertexStorageType::CURRENT_VALUE)
231     {
232         stateManager->invalidateCurrentValueAttrib(attribIndex);
233     }
234 }
235 
hasActiveDynamicAttrib(const gl::Context * context)236 bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context)
237 {
238     const auto &activeLocations =
239         context->getState().getProgramExecutable()->getActiveAttribLocationsMask();
240     gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
241     return activeDynamicAttribs.any();
242 }
243 
updateDirtyAttribs(const gl::Context * context,const gl::AttributesMask & activeDirtyAttribs)244 angle::Result VertexArray11::updateDirtyAttribs(const gl::Context *context,
245                                                 const gl::AttributesMask &activeDirtyAttribs)
246 {
247     const auto &glState  = context->getState();
248     const auto &attribs  = mState.getVertexAttributes();
249     const auto &bindings = mState.getVertexBindings();
250 
251     for (size_t dirtyAttribIndex : activeDirtyAttribs)
252     {
253         mAttribsToTranslate.reset(dirtyAttribIndex);
254 
255         auto *translatedAttrib   = &mTranslatedAttribs[dirtyAttribIndex];
256         const auto &currentValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex);
257 
258         // Record basic attrib info
259         translatedAttrib->attribute        = &attribs[dirtyAttribIndex];
260         translatedAttrib->binding          = &bindings[translatedAttrib->attribute->bindingIndex];
261         translatedAttrib->currentValueType = currentValue.Type;
262         translatedAttrib->divisor =
263             translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
264 
265         switch (mAttributeStorageTypes[dirtyAttribIndex])
266         {
267             case VertexStorageType::DIRECT:
268                 VertexDataManager::StoreDirectAttrib(context, translatedAttrib);
269                 break;
270             case VertexStorageType::STATIC:
271             {
272                 ANGLE_TRY(VertexDataManager::StoreStaticAttrib(context, translatedAttrib));
273                 break;
274             }
275             case VertexStorageType::CURRENT_VALUE:
276                 // Current value attribs are managed by the StateManager11.
277                 break;
278             default:
279                 UNREACHABLE();
280                 break;
281         }
282     }
283 
284     return angle::Result::Continue;
285 }
286 
updateDynamicAttribs(const gl::Context * context,VertexDataManager * vertexDataManager,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLsizei instances,GLint baseVertex,const gl::AttributesMask & activeDynamicAttribs)287 angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context,
288                                                   VertexDataManager *vertexDataManager,
289                                                   GLint firstVertex,
290                                                   GLsizei vertexOrIndexCount,
291                                                   gl::DrawElementsType indexTypeOrInvalid,
292                                                   const void *indices,
293                                                   GLsizei instances,
294                                                   GLint baseVertex,
295                                                   const gl::AttributesMask &activeDynamicAttribs)
296 {
297     const auto &glState  = context->getState();
298     const auto &attribs  = mState.getVertexAttributes();
299     const auto &bindings = mState.getVertexBindings();
300 
301     GLint startVertex;
302     size_t vertexCount;
303     ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
304                                  indices, baseVertex, &startVertex, &vertexCount));
305 
306     for (size_t dynamicAttribIndex : activeDynamicAttribs)
307     {
308         auto *dynamicAttrib      = &mTranslatedAttribs[dynamicAttribIndex];
309         const auto &currentValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex);
310 
311         // Record basic attrib info
312         dynamicAttrib->attribute        = &attribs[dynamicAttribIndex];
313         dynamicAttrib->binding          = &bindings[dynamicAttrib->attribute->bindingIndex];
314         dynamicAttrib->currentValueType = currentValue.Type;
315         dynamicAttrib->divisor = dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
316     }
317 
318     ANGLE_TRY(vertexDataManager->storeDynamicAttribs(
319         context, &mTranslatedAttribs, activeDynamicAttribs, startVertex, vertexCount, instances));
320 
321     VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs,
322                                              vertexCount);
323 
324     return angle::Result::Continue;
325 }
326 
getTranslatedAttribs() const327 const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const
328 {
329     return mTranslatedAttribs;
330 }
331 
markAllAttributeDivisorsForAdjustment(int numViews)332 void VertexArray11::markAllAttributeDivisorsForAdjustment(int numViews)
333 {
334     if (mAppliedNumViewsToDivisor != numViews)
335     {
336         mAppliedNumViewsToDivisor = numViews;
337         mAttribsToTranslate.set();
338         // mDynamicAttribsMask may have already been set (updateVertexAttribStorage
339         // We don't want to override DYNAMIC attribs as they will be handled separately.
340         mAttribsToTranslate = mAttribsToTranslate ^ mDynamicAttribsMask;
341     }
342 }
343 
getCachedIndexInfo() const344 const TranslatedIndexData &VertexArray11::getCachedIndexInfo() const
345 {
346     ASSERT(mCachedIndexInfo.valid());
347     return mCachedIndexInfo.value();
348 }
349 
updateCachedIndexInfo(const TranslatedIndexData & indexInfo)350 void VertexArray11::updateCachedIndexInfo(const TranslatedIndexData &indexInfo)
351 {
352     mCachedIndexInfo = indexInfo;
353 }
354 
isCachedIndexInfoValid() const355 bool VertexArray11::isCachedIndexInfoValid() const
356 {
357     return mCachedIndexInfo.valid();
358 }
359 
getCachedDestinationIndexType() const360 gl::DrawElementsType VertexArray11::getCachedDestinationIndexType() const
361 {
362     return mCachedDestinationIndexType;
363 }
364 
365 }  // namespace rx
366