VertexArray11.cpp (16037B)
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 { 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 31 VertexArray11::~VertexArray11() {} 32 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 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 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 GLuint baseInstance, 132 bool promoteDynamic) 133 { 134 Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer(); 135 StateManager11 *stateManager = renderer->getStateManager(); 136 137 const gl::State &glState = context->getState(); 138 const gl::Program *program = glState.getProgram(); 139 ASSERT(program); 140 const gl::ProgramExecutable &executable = program->getExecutable(); 141 142 mAppliedNumViewsToDivisor = (program->usesMultiview() ? program->getNumViews() : 1); 143 144 if (mAttribsToTranslate.any()) 145 { 146 const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask(); 147 gl::AttributesMask activeDirtyAttribs = (mAttribsToTranslate & activeLocations); 148 if (activeDirtyAttribs.any()) 149 { 150 ANGLE_TRY(updateDirtyAttribs(context, activeDirtyAttribs)); 151 stateManager->invalidateInputLayout(); 152 } 153 } 154 155 if (mDynamicAttribsMask.any()) 156 { 157 const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask(); 158 gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); 159 160 if (activeDynamicAttribs.any()) 161 { 162 ANGLE_TRY(updateDynamicAttribs(context, stateManager->getVertexDataManager(), 163 firstVertex, vertexOrIndexCount, indexTypeOrInvalid, 164 indices, instances, baseVertex, baseInstance, 165 promoteDynamic, activeDynamicAttribs)); 166 stateManager->invalidateInputLayout(); 167 } 168 } 169 170 if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum) 171 { 172 bool restartEnabled = context->getState().isPrimitiveRestartEnabled(); 173 if (!mLastDrawElementsType.valid() || mLastDrawElementsType.value() != indexTypeOrInvalid || 174 mLastDrawElementsIndices.value() != indices || 175 mLastPrimitiveRestartEnabled.value() != restartEnabled) 176 { 177 mLastDrawElementsType = indexTypeOrInvalid; 178 mLastDrawElementsIndices = indices; 179 mLastPrimitiveRestartEnabled = restartEnabled; 180 181 ANGLE_TRY(updateElementArrayStorage(context, vertexOrIndexCount, indexTypeOrInvalid, 182 indices, restartEnabled)); 183 stateManager->invalidateIndexBuffer(); 184 } 185 else if (mCurrentElementArrayStorage == IndexStorageType::Dynamic) 186 { 187 stateManager->invalidateIndexBuffer(); 188 } 189 } 190 191 return angle::Result::Continue; 192 } 193 194 angle::Result VertexArray11::updateElementArrayStorage(const gl::Context *context, 195 GLsizei indexCount, 196 gl::DrawElementsType indexType, 197 const void *indices, 198 bool restartEnabled) 199 { 200 bool usePrimitiveRestartWorkaround = UsePrimitiveRestartWorkaround(restartEnabled, indexType); 201 202 ANGLE_TRY(GetIndexTranslationDestType(context, indexCount, indexType, indices, 203 usePrimitiveRestartWorkaround, 204 &mCachedDestinationIndexType)); 205 206 unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); 207 208 mCurrentElementArrayStorage = 209 ClassifyIndexStorage(context->getState(), mState.getElementArrayBuffer(), indexType, 210 mCachedDestinationIndexType, offset); 211 212 return angle::Result::Continue; 213 } 214 215 void VertexArray11::updateVertexAttribStorage(const gl::Context *context, 216 StateManager11 *stateManager, 217 size_t attribIndex) 218 { 219 const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex); 220 const gl::VertexBinding &binding = mState.getBindingFromAttribIndex(attribIndex); 221 222 VertexStorageType newStorageType = ClassifyAttributeStorage(context, attrib, binding); 223 224 // Note: having an unchanged storage type doesn't mean the attribute is clean. 225 mAttribsToTranslate.set(attribIndex, newStorageType != VertexStorageType::DYNAMIC); 226 227 if (mAttributeStorageTypes[attribIndex] == newStorageType) 228 return; 229 230 mAttributeStorageTypes[attribIndex] = newStorageType; 231 mDynamicAttribsMask.set(attribIndex, newStorageType == VertexStorageType::DYNAMIC); 232 233 if (newStorageType == VertexStorageType::CURRENT_VALUE) 234 { 235 stateManager->invalidateCurrentValueAttrib(attribIndex); 236 } 237 } 238 239 bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context) 240 { 241 const auto &activeLocations = 242 context->getState().getProgramExecutable()->getActiveAttribLocationsMask(); 243 gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); 244 return activeDynamicAttribs.any(); 245 } 246 247 angle::Result VertexArray11::updateDirtyAttribs(const gl::Context *context, 248 const gl::AttributesMask &activeDirtyAttribs) 249 { 250 const auto &glState = context->getState(); 251 const auto &attribs = mState.getVertexAttributes(); 252 const auto &bindings = mState.getVertexBindings(); 253 254 for (size_t dirtyAttribIndex : activeDirtyAttribs) 255 { 256 auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex]; 257 const auto ¤tValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex); 258 259 // Record basic attrib info 260 translatedAttrib->attribute = &attribs[dirtyAttribIndex]; 261 translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex]; 262 translatedAttrib->currentValueType = currentValue.Type; 263 translatedAttrib->divisor = 264 translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; 265 266 switch (mAttributeStorageTypes[dirtyAttribIndex]) 267 { 268 case VertexStorageType::DIRECT: 269 VertexDataManager::StoreDirectAttrib(context, translatedAttrib); 270 break; 271 case VertexStorageType::STATIC: 272 { 273 ANGLE_TRY(VertexDataManager::StoreStaticAttrib(context, translatedAttrib)); 274 break; 275 } 276 case VertexStorageType::CURRENT_VALUE: 277 // Current value attribs are managed by the StateManager11. 278 break; 279 default: 280 UNREACHABLE(); 281 break; 282 } 283 284 // Make sure we reset the dirty bit after the switch because STATIC can early exit. 285 mAttribsToTranslate.reset(dirtyAttribIndex); 286 } 287 288 return angle::Result::Continue; 289 } 290 291 angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context, 292 VertexDataManager *vertexDataManager, 293 GLint firstVertex, 294 GLsizei vertexOrIndexCount, 295 gl::DrawElementsType indexTypeOrInvalid, 296 const void *indices, 297 GLsizei instances, 298 GLint baseVertex, 299 GLuint baseInstance, 300 bool promoteDynamic, 301 const gl::AttributesMask &activeDynamicAttribs) 302 { 303 const auto &glState = context->getState(); 304 const auto &attribs = mState.getVertexAttributes(); 305 const auto &bindings = mState.getVertexBindings(); 306 307 GLint startVertex; 308 size_t vertexCount; 309 ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid, 310 indices, baseVertex, &startVertex, &vertexCount)); 311 312 for (size_t dynamicAttribIndex : activeDynamicAttribs) 313 { 314 auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex]; 315 const auto ¤tValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex); 316 317 // Record basic attrib info 318 dynamicAttrib->attribute = &attribs[dynamicAttribIndex]; 319 dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex]; 320 dynamicAttrib->currentValueType = currentValue.Type; 321 dynamicAttrib->divisor = dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; 322 } 323 324 ANGLE_TRY(vertexDataManager->storeDynamicAttribs(context, &mTranslatedAttribs, 325 activeDynamicAttribs, startVertex, vertexCount, 326 instances, baseInstance)); 327 328 if (promoteDynamic) 329 { 330 VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs, 331 vertexCount); 332 } 333 334 return angle::Result::Continue; 335 } 336 337 const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const 338 { 339 return mTranslatedAttribs; 340 } 341 342 void VertexArray11::markAllAttributeDivisorsForAdjustment(int numViews) 343 { 344 if (mAppliedNumViewsToDivisor != numViews) 345 { 346 mAppliedNumViewsToDivisor = numViews; 347 mAttribsToTranslate.set(); 348 // mDynamicAttribsMask may have already been set (updateVertexAttribStorage 349 // We don't want to override DYNAMIC attribs as they will be handled separately. 350 mAttribsToTranslate = mAttribsToTranslate ^ mDynamicAttribsMask; 351 } 352 } 353 354 const TranslatedIndexData &VertexArray11::getCachedIndexInfo() const 355 { 356 ASSERT(mCachedIndexInfo.valid()); 357 return mCachedIndexInfo.value(); 358 } 359 360 void VertexArray11::updateCachedIndexInfo(const TranslatedIndexData &indexInfo) 361 { 362 mCachedIndexInfo = indexInfo; 363 } 364 365 bool VertexArray11::isCachedIndexInfoValid() const 366 { 367 return mCachedIndexInfo.valid(); 368 } 369 370 gl::DrawElementsType VertexArray11::getCachedDestinationIndexType() const 371 { 372 return mCachedDestinationIndexType; 373 } 374 375 } // namespace rx