Changeset 276569 in webkit
- Timestamp:
- Apr 25, 2021, 12:17:10 PM (5 years ago)
- Location:
- trunk/Source/ThirdParty/ANGLE
- Files:
-
- 7 edited
-
ChangeLog (modified) (1 diff)
-
src/libANGLE/renderer/metal/BufferMtl.h (modified) (4 diffs)
-
src/libANGLE/renderer/metal/BufferMtl.mm (modified) (4 diffs)
-
src/libANGLE/renderer/metal/ContextMtl.h (modified) (1 diff)
-
src/libANGLE/renderer/metal/ContextMtl.mm (modified) (5 diffs)
-
src/libANGLE/renderer/metal/VertexArrayMtl.h (modified) (5 diffs)
-
src/libANGLE/renderer/metal/VertexArrayMtl.mm (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/ThirdParty/ANGLE/ChangeLog
r276568 r276569 1 2021-04-25 Kyle Piddington <kpiddington@apple.com> 2 3 [Metal ANGLE] support primitive restart behavior with simple data types 4 https://bugs.webkit.org/show_bug.cgi?id=225011 5 6 Primitive restart behavior for simple data types is not defined in Metal. Add a pre-draw pass to 7 create a set of restart indices, rather than re-write the index buffer. This pass avoids 8 storing more copies of the index buffer: instead, we cache the location of restart indices, and 9 use them to build draw lists. 10 11 Reviewed by Dean Jackson. 12 13 * src/libANGLE/renderer/metal/BufferMtl.h: 14 * src/libANGLE/renderer/metal/BufferMtl.mm: 15 (rx::IndexConversionBufferMtl::IndexConversionBufferMtl): 16 (rx::BufferMtl::markConversionBuffersDirty): 17 (rx::calculateRestartRanges): 18 (rx::BufferMtl::getRestartIndices): 19 * src/libANGLE/renderer/metal/ContextMtl.h: 20 * src/libANGLE/renderer/metal/ContextMtl.mm: 21 (rx::ContextMtl::drawLineLoopElements): 22 (rx::ContextMtl::drawElementsImpl): 23 (rx::ContextMtl::drawElementsSimpleTypesPrimitiveRestart): Deleted. 24 * src/libANGLE/renderer/metal/VertexArrayMtl.h: 25 * src/libANGLE/renderer/metal/VertexArrayMtl.mm: 26 (rx::VertexArrayMtl::getIndexBuffer): 27 (rx::VertexArrayMtl::getDrawIndices): 28 (rx::VertexArrayMtl::convertIndexBuffer): 29 (rx::VertexArrayMtl::streamIndexBufferFromClient): 30 1 31 2021-04-25 John Cunningham <johncunningham@apple.com> 2 32 -
trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.h
r274547 r276569 25 25 namespace rx 26 26 { 27 28 struct DrawCommandRange 29 { 30 uint32_t count; 31 size_t offset; 32 }; 27 33 struct IndexRange 28 34 { … … 64 70 gl::DrawElementsType elemType, 65 71 bool primitiveRestartEnabled, 66 size_t offsetIn, 67 std::vector<IndexRange> restartRangesIn = std::vector<IndexRange>()); 72 size_t offsetIn); 68 73 const gl::DrawElementsType elemType; 69 74 const size_t offset; 70 75 bool primitiveRestartEnabled; 71 std::vector<IndexRange> restartRanges;72 76 IndexRange getRangeForConvertedBuffer(size_t count); 73 77 … … 164 168 165 169 size_t size() const { return static_cast<size_t>(mState.getSize()); } 166 170 171 const std::vector<IndexRange> & getRestartIndices(ContextMtl * ctx, gl::DrawElementsType indexType); 172 167 173 private: 168 174 angle::Result setDataImpl(const gl::Context *context, … … 200 206 201 207 std::vector<IndexConversionBufferMtl> mIndexConversionBuffers; 202 208 203 209 std::vector<UniformConversionBufferMtl> mUniformConversionBuffers; 210 211 bool mRestartIndicesDirty; 212 std::vector<IndexRange> mRestartIndices; 213 204 214 }; 205 215 -
trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.mm
r274547 r276569 61 61 gl::DrawElementsType elemTypeIn, 62 62 bool primitiveRestartEnabledIn, 63 size_t offsetIn, 64 std::vector<IndexRange> restartRangesIn) 63 size_t offsetIn) 65 64 : ConversionBufferMtl(context, 66 65 kConvertedElementArrayBufferInitialSize, … … 68 67 elemType(elemTypeIn), 69 68 offset(offsetIn), 70 primitiveRestartEnabled(primitiveRestartEnabledIn), 71 restartRanges(restartRangesIn) 72 73 {} 69 primitiveRestartEnabled(primitiveRestartEnabledIn) 70 { 71 } 74 72 75 73 IndexRange IndexConversionBufferMtl::getRangeForConvertedBuffer(size_t count) … … 404 402 buffer.convertedOffset = 0; 405 403 } 404 mRestartIndicesDirty = true; 406 405 } 407 406 … … 413 412 } 414 413 414 template<typename T> 415 static void calculateRestartRanges(ContextMtl* ctx, mtl::BufferRef idxBuffer, std::vector<IndexRange> * ranges) 416 { 417 ranges->clear(); 418 T *bufferData = (T*)(idxBuffer->mapReadOnly(ctx)); 419 for(int i = 0; i < idxBuffer->size()/sizeof(T); i++) 420 { 421 T value = bufferData[i]; 422 if(value == std::numeric_limits<T>::max()) 423 { 424 IndexRange newRange; 425 newRange.restartBegin = i; 426 //Find the end of the restart range. 427 do 428 { 429 ++i; 430 value = bufferData[i]; 431 }while (i < idxBuffer->size() && value == std::numeric_limits<T>::max()); 432 newRange.restartEnd = i-1; 433 ranges->push_back(newRange); 434 } 435 } 436 } 437 438 const std::vector<IndexRange> & BufferMtl::getRestartIndices(ContextMtl * ctx, gl::DrawElementsType indexType) 439 { 440 if(mRestartIndicesDirty) 441 { 442 switch(indexType) 443 { 444 case gl::DrawElementsType::UnsignedByte: 445 calculateRestartRanges<uint8_t>(ctx, getCurrentBuffer(),&mRestartIndices); 446 break; 447 case gl::DrawElementsType::UnsignedShort: 448 calculateRestartRanges<uint16_t>(ctx, getCurrentBuffer(),&mRestartIndices); 449 break; 450 case gl::DrawElementsType::UnsignedInt: 451 calculateRestartRanges<uint32_t>(ctx, getCurrentBuffer(),&mRestartIndices); 452 break; 453 default: 454 ASSERT(false); 455 456 } 457 mRestartIndicesDirty = false; 458 } 459 return mRestartIndices; 460 } 415 461 angle::Result BufferMtl::setDataImpl(const gl::Context *context, 416 462 gl::BufferBinding target, -
trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.h
r274547 r276569 158 158 const GLuint *baseInstances, 159 159 GLsizei drawcount) override; 160 angle::Result drawElementsSimpleTypesPrimitiveRestart(const gl::Context *context,161 gl::PrimitiveMode mode,162 GLsizei count,163 gl::DrawElementsType type,164 const void *indices,165 GLsizei instances);166 167 160 // Device loss 168 161 gl::GraphicsResetStatus getResetStatus() override; -
trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.mm
r275476 r276569 580 580 instances); 581 581 } 582 angle::Result ContextMtl::drawElementsSimpleTypesPrimitiveRestart(const gl::Context *context,583 gl::PrimitiveMode mode,584 GLsizei count,585 gl::DrawElementsType type,586 const void *indices,587 GLsizei instances)588 {589 590 mtl::BufferRef genIdxBuffer;591 uint32_t genIdxBufferOffset;592 uint32_t reservedIndices = count;593 size_t genIndicesCount;594 ANGLE_TRY(AllocateBufferFromPool(this, reservedIndices, &mPrimitiveRestartBuffer, &genIdxBuffer,595 &genIdxBufferOffset));596 switch (mode)597 {598 case gl::PrimitiveMode::Points:599 ANGLE_TRY(getDisplay()->getUtils().generatePrimitiveRestartPointsBuffer(600 this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, true},601 &genIndicesCount));602 break;603 case gl::PrimitiveMode::Lines:604 ANGLE_TRY(getDisplay()->getUtils().generatePrimitiveRestartLinesBuffer(605 this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, true},606 &genIndicesCount));607 break;608 case gl::PrimitiveMode::Triangles:609 ANGLE_TRY(getDisplay()->getUtils().generatePrimitiveRestartTrianglesBuffer(610 this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, true},611 &genIndicesCount));612 break;613 default:614 UNREACHABLE();615 return angle::Result::Stop;616 }617 ANGLE_TRY(mPrimitiveRestartBuffer.commit(this));618 MTLPrimitiveType mtlType = mtl::GetPrimitiveType(mode);619 if (mState.isTransformFeedbackActiveUnpaused())620 {621 ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type,622 reinterpret_cast<const void *>(0), true));623 624 execDrawIndexedInstanced(mtlType, (uint32_t)genIndicesCount, MTLIndexTypeUInt32,625 genIdxBuffer, genIdxBufferOffset, instances);626 }627 ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, false));628 629 execDrawIndexedInstanced(mtlType, (uint32_t)genIndicesCount, MTLIndexTypeUInt32, genIdxBuffer,630 genIdxBufferOffset, instances);631 632 return angle::Result::Continue;633 }634 582 635 583 angle::Result ContextMtl::drawElementsImpl(const gl::Context *context, … … 658 606 size_t convertedOffset = 0; 659 607 gl::DrawElementsType convertedType = type; 660 ANGLE_TRY(mVertexArray->getIndexBuffer(context, type, mode,count, indices, &idxBuffer,608 ANGLE_TRY(mVertexArray->getIndexBuffer(context, type, count, indices, &idxBuffer, 661 609 &convertedOffset, &convertedType)); 662 610 … … 664 612 ASSERT((convertedOffset % mtl::kIndexBufferOffsetAlignment) == 0); 665 613 uint32_t convertedCounti32 = (uint32_t)count; 614 615 //Draw commands will only be broken up if transform feedback is enabled, 616 //if the mode is a simple type, and if the buffer contained any restart 617 //indices. 618 const std::vector<DrawCommandRange> drawCommands = mVertexArray->getDrawIndices(context, type, convertedType, mode, convertedCounti32, convertedOffset); 619 666 620 if (mState.isTransformFeedbackActiveUnpaused()) 667 621 { … … 674 628 { 675 629 // Normal draw 676 mRenderEncoder.drawIndexed(mtlType, convertedCounti32, mtlIdxType, idxBuffer, 677 convertedOffset); 630 for(auto & command : drawCommands) 631 { 632 mRenderEncoder.drawIndexed(mtlType, command.count, mtlIdxType, idxBuffer, 633 command.offset); 634 635 } 678 636 } 679 637 else 680 638 { 681 639 // Instanced draw 682 execDrawIndexedInstanced(mtlType, convertedCounti32, mtlIdxType, idxBuffer, 683 convertedOffset, instanceCount); 640 for(auto & command : drawCommands) 641 { 642 execDrawIndexedInstanced(mtlType, command.count, mtlIdxType, idxBuffer, 643 command.offset, instanceCount); 644 } 684 645 } 685 646 } … … 694 655 { 695 656 // Normal draw 696 mRenderEncoder.drawIndexed(mtlType, convertedCounti32, mtlIdxType, idxBuffer, 697 convertedOffset); 657 for(auto & command : drawCommands) 658 { 659 mRenderEncoder.drawIndexed(mtlType, command.count, mtlIdxType, idxBuffer, 660 command.offset); 661 } 698 662 } 699 663 else 700 664 { 701 665 // Instanced draw 702 execDrawIndexedInstanced(mtlType, convertedCounti32, mtlIdxType, idxBuffer, convertedOffset, 666 for(auto & command : drawCommands) 667 { 668 execDrawIndexedInstanced(mtlType, command.count, mtlIdxType, idxBuffer, command.offset, 703 669 instanceCount); 670 } 704 671 } 705 672 -
trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.h
r273200 r276569 54 54 angle::Result getIndexBuffer(const gl::Context *glContext, 55 55 gl::DrawElementsType indexType, 56 gl::PrimitiveMode primitiveMode,57 56 size_t indexCount, 58 57 const void *sourcePointer, … … 60 59 size_t *idxBufferOffsetOut, 61 60 gl::DrawElementsType *indexTypeOut); 62 61 62 63 std::vector<DrawCommandRange> getDrawIndices(const gl::Context *glContext, 64 gl::DrawElementsType originalIndexType, 65 gl::DrawElementsType indexType, 66 gl::PrimitiveMode primitiveMode, 67 uint32_t indexCount, 68 size_t offset); 69 63 70 // Use to emulate instanced draw for instance <instanceId>. 64 71 // The typical call sequence for emulated instance draw is: … … 86 93 angle::Result convertIndexBuffer(const gl::Context *glContext, 87 94 gl::DrawElementsType indexType, 88 gl::PrimitiveMode mode,89 95 size_t offset, 90 96 mtl::BufferRef *idxBufferOut, … … 92 98 angle::Result streamIndexBufferFromClient(const gl::Context *glContext, 93 99 gl::DrawElementsType indexType, 94 gl::PrimitiveMode primitiveType,95 100 size_t indexCount, 96 101 const void *sourcePointer, … … 128 133 bool isExpandingComponents, 129 134 ConversionBufferMtl *conversion); 130 135 131 136 // These can point to real BufferMtl or converted buffer in mConvertedArrayBufferHolders 132 137 gl::AttribArray<BufferHolderMtl *> mCurrentArrayBuffers; -
trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.mm
r274547 r276569 80 80 gl::DrawElementsType indexType, 81 81 size_t indexCount, 82 gl::PrimitiveMode mode,83 82 bool primitiveRestartEnabled, 84 83 mtl::BufferRef *bufferOut, … … 697 696 angle::Result VertexArrayMtl::getIndexBuffer(const gl::Context *context, 698 697 gl::DrawElementsType type, 699 gl::PrimitiveMode mode,700 698 size_t count, 701 699 const void *indices, … … 709 707 if (!glElementArrayBuffer) 710 708 { 711 ANGLE_TRY(streamIndexBufferFromClient(context, type, mode,count, indices, idxBufferOut,709 ANGLE_TRY(streamIndexBufferFromClient(context, type, count, indices, idxBufferOut, 712 710 idxBufferOffsetOut)); 713 711 } … … 718 716 if (needConversion) 719 717 { 720 ANGLE_TRY(convertIndexBuffer(context, type, mode,convertedOffset, idxBufferOut,718 ANGLE_TRY(convertIndexBuffer(context, type, convertedOffset, idxBufferOut, 721 719 idxBufferOffsetOut)); 722 720 } … … 740 738 } 741 739 740 std::vector<DrawCommandRange> VertexArrayMtl::getDrawIndices(const gl::Context *glContext, 741 gl::DrawElementsType originalIndexType, 742 gl::DrawElementsType indexType, 743 gl::PrimitiveMode primitiveMode, 744 uint32_t indexCount, 745 size_t offset) 746 { 747 ContextMtl *contextMtl = mtl::GetImpl(glContext); 748 std::vector<DrawCommandRange> drawCommands; 749 750 BufferMtl *idxBuffer = mtl::GetImpl(getState().getElementArrayBuffer()); 751 const std::vector<IndexRange> restartIndices = idxBuffer->getRestartIndices(contextMtl, originalIndexType); 752 bool isSimpleType = 753 primitiveMode == gl::PrimitiveMode::Points || 754 primitiveMode == gl::PrimitiveMode::Lines || 755 primitiveMode == gl::PrimitiveMode::Triangles; 756 //If prim restart isn't enabled, or we're drawing a restartable type, or there's no restarts, skip breaking up draw commands. 757 if(restartIndices.size() == 0 || !isSimpleType || !glContext->getState().isPrimitiveRestartEnabled()) 758 { 759 drawCommands.push_back({indexCount, offset}); 760 return drawCommands; 761 } 762 else 763 { 764 //Reminder, offset is in bytes, not elements. 765 //Slice draw commands based off of indices. 766 int nIndicesPerPrimitive; 767 switch(primitiveMode) 768 { 769 case gl::PrimitiveMode::Points: 770 nIndicesPerPrimitive = 1; 771 break; 772 case gl::PrimitiveMode::Lines: 773 nIndicesPerPrimitive = 2; 774 break; 775 case gl::PrimitiveMode::Triangles: 776 nIndicesPerPrimitive = 3; 777 break; 778 default: 779 //Unreachable 780 ASSERT(FALSE); 781 return drawCommands; 782 } 783 const GLuint indexTypeBytes = gl::GetDrawElementsTypeSize(indexType); 784 uint32_t indicesLeft = indexCount; 785 size_t currentIndexOffset = offset / indexTypeBytes; 786 787 for(auto & range : restartIndices) 788 { 789 if(range.restartBegin > currentIndexOffset) 790 { 791 int64_t nIndicesInSlice = ((int64_t)range.restartBegin - currentIndexOffset) - ((int64_t) range.restartBegin - currentIndexOffset) % nIndicesPerPrimitive; 792 size_t restartSize = (range.restartEnd - range.restartBegin) + 1; 793 if(nIndicesInSlice > nIndicesPerPrimitive) 794 drawCommands.push_back({(uint32_t)nIndicesInSlice, currentIndexOffset * indexTypeBytes}); 795 //Account for dropped indices due to incomplete primitives. 796 size_t indicesUsed = ( (range.restartBegin + restartSize) - currentIndexOffset); 797 if(indicesLeft <= indicesUsed) 798 { 799 indicesLeft = 0; 800 } 801 else 802 { 803 indicesLeft -= indicesUsed; 804 } 805 currentIndexOffset = (size_t)(range.restartBegin + restartSize); 806 } 807 //If the initial offset into the index buffer is within a restart zone, move to the end of the restart zone. 808 else if(range.restartEnd >= currentIndexOffset) 809 { 810 size_t restartSize = (range.restartEnd - currentIndexOffset) + 1; 811 if(indicesLeft <= restartSize) 812 { 813 indicesLeft = 0; 814 } 815 else 816 { 817 indicesLeft -= restartSize; 818 } 819 currentIndexOffset = (size_t)(currentIndexOffset + restartSize); 820 } 821 822 } 823 if(indicesLeft >= nIndicesPerPrimitive) 824 drawCommands.push_back({indicesLeft, currentIndexOffset * indexTypeBytes}); 825 return drawCommands; 826 } 827 828 } 829 830 742 831 angle::Result VertexArrayMtl::convertIndexBuffer(const gl::Context *glContext, 743 832 gl::DrawElementsType indexType, 744 gl::PrimitiveMode mode,745 833 size_t offset, 746 834 mtl::BufferRef *idxBufferOut, … … 780 868 ANGLE_TRY(StreamIndexData(contextMtl, &conversion->data, 781 869 idxBuffer->getClientShadowCopyData(contextMtl) + offsetModulo, 782 indexType, indexCount, mode,glState.isPrimitiveRestartEnabled(),870 indexType, indexCount, glState.isPrimitiveRestartEnabled(), 783 871 &conversion->convertedBuffer, &conversion->convertedOffset)); 784 872 } … … 788 876 conversion)); 789 877 } 790 878 //Calculate ranges for prim restart simple types. 791 879 *idxBufferOut = conversion->convertedBuffer; 792 880 *idxBufferOffsetOut = conversion->convertedOffset + alignedOffset; … … 830 918 angle::Result VertexArrayMtl::streamIndexBufferFromClient(const gl::Context *context, 831 919 gl::DrawElementsType indexType, 832 gl::PrimitiveMode mode,833 920 size_t indexCount, 834 921 const void *sourcePointer, … … 840 927 841 928 auto srcData = static_cast<const uint8_t *>(sourcePointer); 842 ANGLE_TRY(StreamIndexData(contextMtl, &mDynamicIndexData, srcData, indexType, indexCount, mode,929 ANGLE_TRY(StreamIndexData(contextMtl, &mDynamicIndexData, srcData, indexType, indexCount, 843 930 context->getState().isPrimitiveRestartEnabled(), idxBufferOut, 844 931 idxBufferOffsetOut));
Note:
See TracChangeset
for help on using the changeset viewer.