Context11.cpp (43321B)
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 // Context11: 7 // D3D11-specific functionality associated with a GL Context. 8 // 9 10 #include "libANGLE/renderer/d3d/d3d11/Context11.h" 11 12 #include "common/entry_points_enum_autogen.h" 13 #include "common/string_utils.h" 14 #include "libANGLE/Context.h" 15 #include "libANGLE/Context.inl.h" 16 #include "libANGLE/MemoryProgramCache.h" 17 #include "libANGLE/renderer/OverlayImpl.h" 18 #include "libANGLE/renderer/d3d/CompilerD3D.h" 19 #include "libANGLE/renderer/d3d/RenderbufferD3D.h" 20 #include "libANGLE/renderer/d3d/SamplerD3D.h" 21 #include "libANGLE/renderer/d3d/ShaderD3D.h" 22 #include "libANGLE/renderer/d3d/TextureD3D.h" 23 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" 24 #include "libANGLE/renderer/d3d/d3d11/Fence11.h" 25 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" 26 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" 27 #include "libANGLE/renderer/d3d/d3d11/Program11.h" 28 #include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h" 29 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" 30 #include "libANGLE/renderer/d3d/d3d11/StateManager11.h" 31 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" 32 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" 33 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 34 35 namespace rx 36 { 37 38 namespace 39 { 40 ANGLE_INLINE bool DrawCallHasDynamicAttribs(const gl::Context *context) 41 { 42 VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(context->getState().getVertexArray()); 43 return vertexArray11->hasActiveDynamicAttrib(context); 44 } 45 46 bool DrawCallHasStreamingVertexArrays(const gl::Context *context, gl::PrimitiveMode mode) 47 { 48 // Direct drawing doesn't support dynamic attribute storage since it needs the first and count 49 // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported 50 // either since we need to simulate them in D3D. 51 if (DrawCallHasDynamicAttribs(context) || mode == gl::PrimitiveMode::LineLoop || 52 mode == gl::PrimitiveMode::TriangleFan) 53 { 54 return true; 55 } 56 57 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(context->getState().getProgram()); 58 if (InstancedPointSpritesActive(programD3D, mode)) 59 { 60 return true; 61 } 62 63 return false; 64 } 65 66 bool DrawCallHasStreamingElementArray(const gl::Context *context, gl::DrawElementsType srcType) 67 { 68 const gl::State &glState = context->getState(); 69 gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer(); 70 71 bool primitiveRestartWorkaround = 72 UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType); 73 const gl::DrawElementsType dstType = 74 (srcType == gl::DrawElementsType::UnsignedInt || primitiveRestartWorkaround) 75 ? gl::DrawElementsType::UnsignedInt 76 : gl::DrawElementsType::UnsignedShort; 77 78 // Not clear where the offset comes from here. 79 switch (ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0)) 80 { 81 case IndexStorageType::Dynamic: 82 return true; 83 case IndexStorageType::Direct: 84 return false; 85 case IndexStorageType::Static: 86 { 87 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer); 88 StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer(); 89 return (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != dstType); 90 } 91 default: 92 UNREACHABLE(); 93 return true; 94 } 95 } 96 97 template <typename IndirectBufferT> 98 angle::Result ReadbackIndirectBuffer(const gl::Context *context, 99 const void *indirect, 100 const IndirectBufferT **bufferPtrOut) 101 { 102 const gl::State &glState = context->getState(); 103 gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); 104 ASSERT(drawIndirectBuffer); 105 Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); 106 uintptr_t offset = reinterpret_cast<uintptr_t>(indirect); 107 108 const uint8_t *bufferData = nullptr; 109 ANGLE_TRY(storage->getData(context, &bufferData)); 110 ASSERT(bufferData); 111 112 *bufferPtrOut = reinterpret_cast<const IndirectBufferT *>(bufferData + offset); 113 return angle::Result::Continue; 114 } 115 } // anonymous namespace 116 117 Context11::Context11(const gl::State &state, gl::ErrorSet *errorSet, Renderer11 *renderer) 118 : ContextD3D(state, errorSet), mRenderer(renderer) 119 {} 120 121 Context11::~Context11() {} 122 123 angle::Result Context11::initialize() 124 { 125 return angle::Result::Continue; 126 } 127 128 void Context11::onDestroy(const gl::Context *context) 129 { 130 mIncompleteTextures.onDestroy(context); 131 } 132 133 CompilerImpl *Context11::createCompiler() 134 { 135 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) 136 { 137 return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT); 138 } 139 else 140 { 141 return new CompilerD3D(SH_HLSL_4_1_OUTPUT); 142 } 143 } 144 145 ShaderImpl *Context11::createShader(const gl::ShaderState &data) 146 { 147 return new ShaderD3D(data, mRenderer); 148 } 149 150 ProgramImpl *Context11::createProgram(const gl::ProgramState &data) 151 { 152 return new Program11(data, mRenderer); 153 } 154 155 FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data) 156 { 157 return new Framebuffer11(data, mRenderer); 158 } 159 160 TextureImpl *Context11::createTexture(const gl::TextureState &state) 161 { 162 switch (state.getType()) 163 { 164 case gl::TextureType::_2D: 165 // GL_TEXTURE_VIDEO_IMAGE_WEBGL maps to native 2D texture on Windows platform 166 case gl::TextureType::VideoImage: 167 return new TextureD3D_2D(state, mRenderer); 168 case gl::TextureType::CubeMap: 169 return new TextureD3D_Cube(state, mRenderer); 170 case gl::TextureType::_3D: 171 return new TextureD3D_3D(state, mRenderer); 172 case gl::TextureType::_2DArray: 173 return new TextureD3D_2DArray(state, mRenderer); 174 case gl::TextureType::External: 175 return new TextureD3D_External(state, mRenderer); 176 case gl::TextureType::_2DMultisample: 177 return new TextureD3D_2DMultisample(state, mRenderer); 178 case gl::TextureType::_2DMultisampleArray: 179 return new TextureD3D_2DMultisampleArray(state, mRenderer); 180 case gl::TextureType::Buffer: 181 return new TextureD3D_Buffer(state, mRenderer); 182 default: 183 UNREACHABLE(); 184 } 185 186 return nullptr; 187 } 188 189 RenderbufferImpl *Context11::createRenderbuffer(const gl::RenderbufferState &state) 190 { 191 return new RenderbufferD3D(state, mRenderer); 192 } 193 194 BufferImpl *Context11::createBuffer(const gl::BufferState &state) 195 { 196 Buffer11 *buffer = new Buffer11(state, mRenderer); 197 mRenderer->onBufferCreate(buffer); 198 return buffer; 199 } 200 201 VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data) 202 { 203 return new VertexArray11(data); 204 } 205 206 QueryImpl *Context11::createQuery(gl::QueryType type) 207 { 208 return new Query11(mRenderer, type); 209 } 210 211 FenceNVImpl *Context11::createFenceNV() 212 { 213 return new FenceNV11(mRenderer); 214 } 215 216 SyncImpl *Context11::createSync() 217 { 218 return new Sync11(mRenderer); 219 } 220 221 TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state) 222 { 223 return new TransformFeedback11(state, mRenderer); 224 } 225 226 SamplerImpl *Context11::createSampler(const gl::SamplerState &state) 227 { 228 return new SamplerD3D(state); 229 } 230 231 ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data) 232 { 233 return new ProgramPipeline11(data); 234 } 235 236 MemoryObjectImpl *Context11::createMemoryObject() 237 { 238 UNREACHABLE(); 239 return nullptr; 240 } 241 242 SemaphoreImpl *Context11::createSemaphore() 243 { 244 UNREACHABLE(); 245 return nullptr; 246 } 247 248 OverlayImpl *Context11::createOverlay(const gl::OverlayState &state) 249 { 250 // Not implemented. 251 return new OverlayImpl(state); 252 } 253 254 angle::Result Context11::flush(const gl::Context *context) 255 { 256 return mRenderer->flush(this); 257 } 258 259 angle::Result Context11::finish(const gl::Context *context) 260 { 261 return mRenderer->finish(this); 262 } 263 264 angle::Result Context11::drawArrays(const gl::Context *context, 265 gl::PrimitiveMode mode, 266 GLint first, 267 GLsizei count) 268 { 269 ASSERT(count > 0); 270 ANGLE_TRY(mRenderer->getStateManager()->updateState( 271 context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true)); 272 return mRenderer->drawArrays(context, mode, first, count, 0, 0, false); 273 } 274 275 angle::Result Context11::drawArraysInstanced(const gl::Context *context, 276 gl::PrimitiveMode mode, 277 GLint first, 278 GLsizei count, 279 GLsizei instanceCount) 280 { 281 ASSERT(count > 0); 282 ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count, 283 gl::DrawElementsType::InvalidEnum, nullptr, 284 instanceCount, 0, 0, true)); 285 return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0, true); 286 } 287 288 angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context, 289 gl::PrimitiveMode mode, 290 GLint first, 291 GLsizei count, 292 GLsizei instanceCount, 293 GLuint baseInstance) 294 { 295 ASSERT(count > 0); 296 ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count, 297 gl::DrawElementsType::InvalidEnum, nullptr, 298 instanceCount, 0, baseInstance, true)); 299 return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance, true); 300 } 301 302 ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context, 303 gl::PrimitiveMode mode, 304 GLsizei indexCount, 305 gl::DrawElementsType indexType, 306 const void *indices, 307 GLsizei instanceCount, 308 GLint baseVertex, 309 GLuint baseInstance, 310 bool promoteDynamic, 311 bool isInstancedDraw) 312 { 313 ASSERT(indexCount > 0); 314 315 if (DrawCallHasDynamicAttribs(context)) 316 { 317 gl::IndexRange indexRange; 318 ANGLE_TRY(context->getState().getVertexArray()->getIndexRange( 319 context, indexType, indexCount, indices, &indexRange)); 320 GLint startVertex; 321 ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex, 322 &startVertex)); 323 ANGLE_TRY(mRenderer->getStateManager()->updateState( 324 context, mode, startVertex, indexCount, indexType, indices, instanceCount, baseVertex, 325 baseInstance, promoteDynamic)); 326 return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices, 327 instanceCount, baseVertex, baseInstance, isInstancedDraw); 328 } 329 else 330 { 331 ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType, 332 indices, instanceCount, baseVertex, 333 baseInstance, promoteDynamic)); 334 return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices, 335 instanceCount, baseVertex, baseInstance, isInstancedDraw); 336 } 337 } 338 339 angle::Result Context11::drawElements(const gl::Context *context, 340 gl::PrimitiveMode mode, 341 GLsizei count, 342 gl::DrawElementsType type, 343 const void *indices) 344 { 345 return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false); 346 } 347 348 angle::Result Context11::drawElementsBaseVertex(const gl::Context *context, 349 gl::PrimitiveMode mode, 350 GLsizei count, 351 gl::DrawElementsType type, 352 const void *indices, 353 GLint baseVertex) 354 { 355 return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false); 356 } 357 358 angle::Result Context11::drawElementsInstanced(const gl::Context *context, 359 gl::PrimitiveMode mode, 360 GLsizei count, 361 gl::DrawElementsType type, 362 const void *indices, 363 GLsizei instances) 364 { 365 return drawElementsImpl(context, mode, count, type, indices, instances, 0, 0, true, true); 366 } 367 368 angle::Result Context11::drawElementsInstancedBaseVertex(const gl::Context *context, 369 gl::PrimitiveMode mode, 370 GLsizei count, 371 gl::DrawElementsType type, 372 const void *indices, 373 GLsizei instances, 374 GLint baseVertex) 375 { 376 return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0, true, 377 true); 378 } 379 380 angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context, 381 gl::PrimitiveMode mode, 382 GLsizei count, 383 gl::DrawElementsType type, 384 const void *indices, 385 GLsizei instances, 386 GLint baseVertex, 387 GLuint baseInstance) 388 { 389 return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 390 baseInstance, true, true); 391 } 392 393 angle::Result Context11::drawRangeElements(const gl::Context *context, 394 gl::PrimitiveMode mode, 395 GLuint start, 396 GLuint end, 397 GLsizei count, 398 gl::DrawElementsType type, 399 const void *indices) 400 { 401 return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false); 402 } 403 404 angle::Result Context11::drawRangeElementsBaseVertex(const gl::Context *context, 405 gl::PrimitiveMode mode, 406 GLuint start, 407 GLuint end, 408 GLsizei count, 409 gl::DrawElementsType type, 410 const void *indices, 411 GLint baseVertex) 412 { 413 return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false); 414 } 415 416 angle::Result Context11::drawArraysIndirect(const gl::Context *context, 417 gl::PrimitiveMode mode, 418 const void *indirect) 419 { 420 if (DrawCallHasStreamingVertexArrays(context, mode)) 421 { 422 const gl::DrawArraysIndirectCommand *cmd = nullptr; 423 ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd)); 424 425 ANGLE_TRY(mRenderer->getStateManager()->updateState( 426 context, mode, cmd->first, cmd->count, gl::DrawElementsType::InvalidEnum, nullptr, 427 cmd->instanceCount, 0, 0, true)); 428 return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount, 429 cmd->baseInstance, true); 430 } 431 else 432 { 433 ANGLE_TRY(mRenderer->getStateManager()->updateState( 434 context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true)); 435 return mRenderer->drawArraysIndirect(context, indirect); 436 } 437 } 438 439 angle::Result Context11::drawElementsIndirect(const gl::Context *context, 440 gl::PrimitiveMode mode, 441 gl::DrawElementsType type, 442 const void *indirect) 443 { 444 if (DrawCallHasStreamingVertexArrays(context, mode) || 445 DrawCallHasStreamingElementArray(context, type)) 446 { 447 const gl::DrawElementsIndirectCommand *cmd = nullptr; 448 ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd)); 449 450 const GLuint typeBytes = gl::GetDrawElementsTypeSize(type); 451 const void *indices = 452 reinterpret_cast<const void *>(static_cast<uintptr_t>(cmd->firstIndex * typeBytes)); 453 454 // We must explicitly resolve the index range for the slow-path indirect drawElements to 455 // make sure we are using the correct 'baseVertex'. This parameter does not exist for the 456 // direct drawElements. 457 gl::IndexRange indexRange; 458 ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count, 459 indices, &indexRange)); 460 461 GLint startVertex; 462 ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, cmd->baseVertex, 463 &startVertex)); 464 465 ANGLE_TRY(mRenderer->getStateManager()->updateState( 466 context, mode, startVertex, cmd->count, type, indices, cmd->primCount, cmd->baseVertex, 467 cmd->baseInstance, true)); 468 return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start), 469 cmd->count, type, indices, cmd->primCount, 0, 0, true); 470 } 471 else 472 { 473 ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0, 474 0, 0, true)); 475 return mRenderer->drawElementsIndirect(context, indirect); 476 } 477 } 478 479 #define DRAW_ARRAYS__ \ 480 { \ 481 ANGLE_TRY(mRenderer->getStateManager()->updateState( \ 482 context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \ 483 nullptr, 0, 0, 0, false)); \ 484 ANGLE_TRY( \ 485 mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], 0, 0, false)); \ 486 } 487 #define DRAW_ARRAYS_INSTANCED_ \ 488 { \ 489 ANGLE_TRY(mRenderer->getStateManager()->updateState( \ 490 context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \ 491 nullptr, instanceCounts[drawID], 0, 0, false)); \ 492 ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], \ 493 instanceCounts[drawID], 0, true)); \ 494 } 495 #define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE \ 496 { \ 497 ANGLE_TRY(mRenderer->getStateManager()->updateState( \ 498 context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \ 499 nullptr, instanceCounts[drawID], 0, baseInstances[drawID], false)); \ 500 ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], \ 501 instanceCounts[drawID], baseInstances[drawID], true)); \ 502 } 503 #define DRAW_ELEMENTS__ \ 504 { \ 505 ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], 0, 0, 0, \ 506 false, false)); \ 507 } 508 #define DRAW_ELEMENTS_INSTANCED_ \ 509 { \ 510 ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \ 511 instanceCounts[drawID], 0, 0, false, true)); \ 512 } 513 #define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE \ 514 { \ 515 ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \ 516 instanceCounts[drawID], baseVertices[drawID], \ 517 baseInstances[drawID], false, true)); \ 518 } 519 520 #define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi 521 522 #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \ 523 for (GLsizei drawID = 0; drawID < drawcount; ++drawID) \ 524 { \ 525 if (ANGLE_NOOP_DRAW(instanced)) \ 526 { \ 527 continue; \ 528 } \ 529 ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID); \ 530 ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]); \ 531 ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]); \ 532 ASSERT(counts[drawID] > 0); \ 533 DRAW_CALL(drawType, instanced, bvbi); \ 534 ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \ 535 gl::MarkShaderStorageUsage(context); \ 536 } 537 538 angle::Result Context11::multiDrawArrays(const gl::Context *context, 539 gl::PrimitiveMode mode, 540 const GLint *firsts, 541 const GLsizei *counts, 542 GLsizei drawcount) 543 { 544 gl::Program *programObject = context->getState().getLinkedProgram(context); 545 const bool hasDrawID = programObject && programObject->hasDrawIDUniform(); 546 if (hasDrawID) 547 { 548 MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0) 549 } 550 else 551 { 552 MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0) 553 } 554 555 return angle::Result::Continue; 556 } 557 558 angle::Result Context11::multiDrawArraysInstanced(const gl::Context *context, 559 gl::PrimitiveMode mode, 560 const GLint *firsts, 561 const GLsizei *counts, 562 const GLsizei *instanceCounts, 563 GLsizei drawcount) 564 { 565 gl::Program *programObject = context->getState().getLinkedProgram(context); 566 const bool hasDrawID = programObject && programObject->hasDrawIDUniform(); 567 if (hasDrawID) 568 { 569 MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0) 570 } 571 else 572 { 573 MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0) 574 } 575 576 return angle::Result::Continue; 577 } 578 579 angle::Result Context11::multiDrawArraysIndirect(const gl::Context *context, 580 gl::PrimitiveMode mode, 581 const void *indirect, 582 GLsizei drawcount, 583 GLsizei stride) 584 { 585 return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride); 586 } 587 588 angle::Result Context11::multiDrawElements(const gl::Context *context, 589 gl::PrimitiveMode mode, 590 const GLsizei *counts, 591 gl::DrawElementsType type, 592 const GLvoid *const *indices, 593 GLsizei drawcount) 594 { 595 gl::Program *programObject = context->getState().getLinkedProgram(context); 596 const bool hasDrawID = programObject && programObject->hasDrawIDUniform(); 597 if (hasDrawID) 598 { 599 MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0) 600 } 601 else 602 { 603 MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0) 604 } 605 606 return angle::Result::Continue; 607 } 608 609 angle::Result Context11::multiDrawElementsInstanced(const gl::Context *context, 610 gl::PrimitiveMode mode, 611 const GLsizei *counts, 612 gl::DrawElementsType type, 613 const GLvoid *const *indices, 614 const GLsizei *instanceCounts, 615 GLsizei drawcount) 616 { 617 gl::Program *programObject = context->getState().getLinkedProgram(context); 618 const bool hasDrawID = programObject && programObject->hasDrawIDUniform(); 619 if (hasDrawID) 620 { 621 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0) 622 } 623 else 624 { 625 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0) 626 } 627 628 return angle::Result::Continue; 629 } 630 631 angle::Result Context11::multiDrawElementsIndirect(const gl::Context *context, 632 gl::PrimitiveMode mode, 633 gl::DrawElementsType type, 634 const void *indirect, 635 GLsizei drawcount, 636 GLsizei stride) 637 { 638 return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount, 639 stride); 640 } 641 642 angle::Result Context11::multiDrawArraysInstancedBaseInstance(const gl::Context *context, 643 gl::PrimitiveMode mode, 644 const GLint *firsts, 645 const GLsizei *counts, 646 const GLsizei *instanceCounts, 647 const GLuint *baseInstances, 648 GLsizei drawcount) 649 { 650 gl::Program *programObject = context->getState().getLinkedProgram(context); 651 const bool hasDrawID = programObject && programObject->hasDrawIDUniform(); 652 const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform(); 653 ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance); 654 655 if (hasDrawID && hasBaseInstance) 656 { 657 MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1) 658 } 659 else if (hasDrawID) 660 { 661 MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0) 662 } 663 else if (hasBaseInstance) 664 { 665 MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1) 666 } 667 else 668 { 669 MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0) 670 } 671 672 return angle::Result::Continue; 673 } 674 675 angle::Result Context11::multiDrawElementsInstancedBaseVertexBaseInstance( 676 const gl::Context *context, 677 gl::PrimitiveMode mode, 678 const GLsizei *counts, 679 gl::DrawElementsType type, 680 const GLvoid *const *indices, 681 const GLsizei *instanceCounts, 682 const GLint *baseVertices, 683 const GLuint *baseInstances, 684 GLsizei drawcount) 685 { 686 gl::Program *programObject = context->getState().getLinkedProgram(context); 687 const bool hasDrawID = programObject && programObject->hasDrawIDUniform(); 688 const bool hasBaseVertex = programObject && programObject->hasBaseVertexUniform(); 689 const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform(); 690 ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance); 691 692 if (hasDrawID) 693 { 694 if (hasBaseVertex) 695 { 696 if (hasBaseInstance) 697 { 698 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1) 699 } 700 else 701 { 702 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0) 703 } 704 } 705 else 706 { 707 if (hasBaseInstance) 708 { 709 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1) 710 } 711 else 712 { 713 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0) 714 } 715 } 716 } 717 else 718 { 719 if (hasBaseVertex) 720 { 721 if (hasBaseInstance) 722 { 723 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1) 724 } 725 else 726 { 727 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0) 728 } 729 } 730 else 731 { 732 if (hasBaseInstance) 733 { 734 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1) 735 } 736 else 737 { 738 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0) 739 } 740 } 741 } 742 743 return angle::Result::Continue; 744 } 745 746 gl::GraphicsResetStatus Context11::getResetStatus() 747 { 748 return mRenderer->getResetStatus(); 749 } 750 751 angle::Result Context11::insertEventMarker(GLsizei length, const char *marker) 752 { 753 mRenderer->getDebugAnnotatorContext()->setMarker(marker); 754 return angle::Result::Continue; 755 } 756 757 angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker) 758 { 759 mRenderer->getDebugAnnotatorContext()->beginEvent(angle::EntryPoint::GLPushGroupMarkerEXT, 760 marker, marker); 761 mMarkerStack.push(std::string(marker)); 762 return angle::Result::Continue; 763 } 764 765 angle::Result Context11::popGroupMarker() 766 { 767 const char *marker = nullptr; 768 if (!mMarkerStack.empty()) 769 { 770 marker = mMarkerStack.top().c_str(); 771 mMarkerStack.pop(); 772 mRenderer->getDebugAnnotatorContext()->endEvent(marker, 773 angle::EntryPoint::GLPopGroupMarkerEXT); 774 } 775 return angle::Result::Continue; 776 } 777 778 angle::Result Context11::pushDebugGroup(const gl::Context *context, 779 GLenum source, 780 GLuint id, 781 const std::string &message) 782 { 783 // Fall through to the EXT_debug_marker functions 784 return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str()); 785 } 786 787 angle::Result Context11::popDebugGroup(const gl::Context *context) 788 { 789 // Fall through to the EXT_debug_marker functions 790 return popGroupMarker(); 791 } 792 793 angle::Result Context11::syncState(const gl::Context *context, 794 const gl::State::DirtyBits &dirtyBits, 795 const gl::State::DirtyBits &bitMask, 796 gl::Command command) 797 { 798 mRenderer->getStateManager()->syncState(context, dirtyBits, command); 799 return angle::Result::Continue; 800 } 801 802 GLint Context11::getGPUDisjoint() 803 { 804 return mRenderer->getGPUDisjoint(); 805 } 806 807 GLint64 Context11::getTimestamp() 808 { 809 return mRenderer->getTimestamp(); 810 } 811 812 angle::Result Context11::onMakeCurrent(const gl::Context *context) 813 { 814 // Immediately return if the device has been lost. 815 if (!mRenderer->getDevice()) 816 { 817 return angle::Result::Continue; 818 } 819 820 return mRenderer->getStateManager()->onMakeCurrent(context); 821 } 822 823 gl::Caps Context11::getNativeCaps() const 824 { 825 gl::Caps caps = mRenderer->getNativeCaps(); 826 827 // For pixel shaders, the render targets and unordered access views share the same resource 828 // slots, so the maximum number of fragment shader outputs depends on the current context 829 // version: 830 // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) 831 // as the value of max draw buffers because UAVs are not used. 832 // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8 833 // slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value 834 // of max combined shader output resources is limited to 7, thus only 7 RTV slots can be 835 // used simultaneously. 836 // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64 837 // slots. Currently we allocate 60 slots for combined shader output resources, so we can use 838 // at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously. 839 if (mState.getClientVersion() >= gl::ES_3_1 && 840 mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0) 841 { 842 caps.maxDrawBuffers = caps.maxCombinedShaderOutputResources; 843 caps.maxColorAttachments = caps.maxCombinedShaderOutputResources; 844 } 845 846 return caps; 847 } 848 849 const gl::TextureCapsMap &Context11::getNativeTextureCaps() const 850 { 851 return mRenderer->getNativeTextureCaps(); 852 } 853 854 const gl::Extensions &Context11::getNativeExtensions() const 855 { 856 return mRenderer->getNativeExtensions(); 857 } 858 859 const gl::Limitations &Context11::getNativeLimitations() const 860 { 861 return mRenderer->getNativeLimitations(); 862 } 863 864 ShPixelLocalStorageType Context11::getNativePixelLocalStorageType() const 865 { 866 return mRenderer->getNativePixelLocalStorageType(); 867 } 868 869 angle::Result Context11::dispatchCompute(const gl::Context *context, 870 GLuint numGroupsX, 871 GLuint numGroupsY, 872 GLuint numGroupsZ) 873 { 874 return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ); 875 } 876 877 angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) 878 { 879 return mRenderer->dispatchComputeIndirect(context, indirect); 880 } 881 882 angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context, 883 gl::PrimitiveMode drawMode) 884 { 885 const auto &glState = context->getState(); 886 const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray()); 887 const auto *drawFBO = glState.getDrawFramebuffer(); 888 gl::Program *program = glState.getProgram(); 889 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); 890 891 programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); 892 programD3D->updateCachedOutputLayout(context, drawFBO); 893 894 bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout(); 895 bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode); 896 bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout(); 897 898 if (!recompileVS && !recompileGS && !recompilePS) 899 { 900 return angle::Result::Continue; 901 } 902 903 // Load the compiler if necessary and recompile the programs. 904 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this)); 905 906 gl::InfoLog infoLog; 907 908 if (recompileVS) 909 { 910 ShaderExecutableD3D *vertexExe = nullptr; 911 ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(this, &vertexExe, &infoLog)); 912 if (!programD3D->hasVertexExecutableForCachedInputLayout()) 913 { 914 ASSERT(infoLog.getLength() > 0); 915 ERR() << "Error compiling dynamic vertex executable: " << infoLog.str(); 916 ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic vertex executable"); 917 } 918 } 919 920 if (recompileGS) 921 { 922 ShaderExecutableD3D *geometryExe = nullptr; 923 ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(this, glState, drawMode, 924 &geometryExe, &infoLog)); 925 if (!programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode)) 926 { 927 ASSERT(infoLog.getLength() > 0); 928 ERR() << "Error compiling dynamic geometry executable: " << infoLog.str(); 929 ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic geometry executable"); 930 } 931 } 932 933 if (recompilePS) 934 { 935 ShaderExecutableD3D *pixelExe = nullptr; 936 ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(this, &pixelExe, &infoLog)); 937 if (!programD3D->hasPixelExecutableForCachedOutputLayout()) 938 { 939 ASSERT(infoLog.getLength() > 0); 940 ERR() << "Error compiling dynamic pixel executable: " << infoLog.str(); 941 ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic pixel executable"); 942 } 943 } 944 945 // Refresh the program cache entry. 946 if (mMemoryProgramCache) 947 { 948 ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program)); 949 } 950 951 return angle::Result::Continue; 952 } 953 954 angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context) 955 { 956 const auto &glState = context->getState(); 957 gl::Program *program = glState.getProgram(); 958 ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); 959 960 programD3D->updateCachedComputeImage2DBindLayout(context); 961 962 bool recompileCS = !programD3D->hasComputeExecutableForCachedImage2DBindLayout(); 963 964 if (!recompileCS) 965 { 966 return angle::Result::Continue; 967 } 968 969 // Load the compiler if necessary and recompile the programs. 970 ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this)); 971 972 gl::InfoLog infoLog; 973 974 ShaderExecutableD3D *computeExe = nullptr; 975 ANGLE_TRY( 976 programD3D->getComputeExecutableForImage2DBindLayout(context, this, &computeExe, &infoLog)); 977 if (!programD3D->hasComputeExecutableForCachedImage2DBindLayout()) 978 { 979 ASSERT(infoLog.getLength() > 0); 980 ERR() << "Dynamic recompilation error log: " << infoLog.str(); 981 ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable"); 982 } 983 984 // Refresh the program cache entry. 985 if (mMemoryProgramCache) 986 { 987 ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program)); 988 } 989 990 return angle::Result::Continue; 991 } 992 993 angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers) 994 { 995 return angle::Result::Continue; 996 } 997 998 angle::Result Context11::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) 999 { 1000 return angle::Result::Continue; 1001 } 1002 1003 angle::Result Context11::getIncompleteTexture(const gl::Context *context, 1004 gl::TextureType type, 1005 gl::Texture **textureOut) 1006 { 1007 return mIncompleteTextures.getIncompleteTexture(context, type, gl::SamplerFormat::Float, this, 1008 textureOut); 1009 } 1010 1011 angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context *context, 1012 gl::Texture *glTexture) 1013 { 1014 ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample); 1015 TextureD3D *textureD3D = GetImplAs<TextureD3D>(glTexture); 1016 gl::ImageIndex index = gl::ImageIndex::Make2DMultisample(); 1017 RenderTargetD3D *renderTarget = nullptr; 1018 GLsizei texSamples = textureD3D->getRenderToTextureSamples(); 1019 ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget)); 1020 return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1021 1.0f, 0); 1022 } 1023 1024 void Context11::handleResult(HRESULT hr, 1025 const char *message, 1026 const char *file, 1027 const char *function, 1028 unsigned int line) 1029 { 1030 ASSERT(FAILED(hr)); 1031 1032 GLenum glErrorCode = DefaultGLErrorCode(hr); 1033 1034 std::stringstream errorStream; 1035 errorStream << "Internal D3D11 error: " << gl::FmtHR(hr); 1036 1037 if (d3d11::isDeviceLostError(hr)) 1038 { 1039 HRESULT removalReason = mRenderer->getDevice()->GetDeviceRemovedReason(); 1040 errorStream << " (removal reason: " << gl::FmtHR(removalReason) << ")"; 1041 mRenderer->notifyDeviceLost(); 1042 } 1043 1044 errorStream << ": " << message; 1045 1046 mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line); 1047 } 1048 } // namespace rx