Diff
Modified: trunk/Source/ThirdParty/ANGLE/ChangeLog (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/ChangeLog 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/ChangeLog 2021-04-25 19:17:10 UTC (rev 276569)
@@ -1,3 +1,33 @@
+2021-04-25 Kyle Piddington <[email protected]>
+
+ [Metal ANGLE] support primitive restart behavior with simple data types
+ https://bugs.webkit.org/show_bug.cgi?id=225011
+
+ Primitive restart behavior for simple data types is not defined in Metal. Add a pre-draw pass to
+ create a set of restart indices, rather than re-write the index buffer. This pass avoids
+ storing more copies of the index buffer: instead, we cache the location of restart indices, and
+ use them to build draw lists.
+
+ Reviewed by Dean Jackson.
+
+ * src/libANGLE/renderer/metal/BufferMtl.h:
+ * src/libANGLE/renderer/metal/BufferMtl.mm:
+ (rx::IndexConversionBufferMtl::IndexConversionBufferMtl):
+ (rx::BufferMtl::markConversionBuffersDirty):
+ (rx::calculateRestartRanges):
+ (rx::BufferMtl::getRestartIndices):
+ * src/libANGLE/renderer/metal/ContextMtl.h:
+ * src/libANGLE/renderer/metal/ContextMtl.mm:
+ (rx::ContextMtl::drawLineLoopElements):
+ (rx::ContextMtl::drawElementsImpl):
+ (rx::ContextMtl::drawElementsSimpleTypesPrimitiveRestart): Deleted.
+ * src/libANGLE/renderer/metal/VertexArrayMtl.h:
+ * src/libANGLE/renderer/metal/VertexArrayMtl.mm:
+ (rx::VertexArrayMtl::getIndexBuffer):
+ (rx::VertexArrayMtl::getDrawIndices):
+ (rx::VertexArrayMtl::convertIndexBuffer):
+ (rx::VertexArrayMtl::streamIndexBufferFromClient):
+
2021-04-25 John Cunningham <[email protected]>
[Metal ANGLE] Temporarily remove AST validation even for debug builds
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.h (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.h 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.h 2021-04-25 19:17:10 UTC (rev 276569)
@@ -24,6 +24,12 @@
namespace rx
{
+
+struct DrawCommandRange
+{
+ uint32_t count;
+ size_t offset;
+};
struct IndexRange
{
size_t restartBegin;
@@ -63,12 +69,10 @@
IndexConversionBufferMtl(ContextMtl *context,
gl::DrawElementsType elemType,
bool primitiveRestartEnabled,
- size_t offsetIn,
- std::vector<IndexRange> restartRangesIn = std::vector<IndexRange>());
+ size_t offsetIn);
const gl::DrawElementsType elemType;
const size_t offset;
bool primitiveRestartEnabled;
- std::vector<IndexRange> restartRanges;
IndexRange getRangeForConvertedBuffer(size_t count);
};
@@ -163,7 +167,9 @@
void markConversionBuffersDirty();
size_t size() const { return static_cast<size_t>(mState.getSize()); }
-
+
+ const std::vector<IndexRange> & getRestartIndices(ContextMtl * ctx, gl::DrawElementsType indexType);
+
private:
angle::Result setDataImpl(const gl::Context *context,
gl::BufferBinding target,
@@ -199,8 +205,12 @@
std::vector<VertexConversionBufferMtl> mVertexConversionBuffers;
std::vector<IndexConversionBufferMtl> mIndexConversionBuffers;
-
+
std::vector<UniformConversionBufferMtl> mUniformConversionBuffers;
+
+ bool mRestartIndicesDirty;
+ std::vector<IndexRange> mRestartIndices;
+
};
class SimpleWeakBufferHolderMtl : public BufferHolderMtl
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.mm (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.mm 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/BufferMtl.mm 2021-04-25 19:17:10 UTC (rev 276569)
@@ -60,18 +60,16 @@
IndexConversionBufferMtl::IndexConversionBufferMtl(ContextMtl *context,
gl::DrawElementsType elemTypeIn,
bool primitiveRestartEnabledIn,
- size_t offsetIn,
- std::vector<IndexRange> restartRangesIn)
+ size_t offsetIn)
: ConversionBufferMtl(context,
kConvertedElementArrayBufferInitialSize,
mtl::kIndexBufferOffsetAlignment),
elemType(elemTypeIn),
offset(offsetIn),
- primitiveRestartEnabled(primitiveRestartEnabledIn),
- restartRanges(restartRangesIn)
+ primitiveRestartEnabled(primitiveRestartEnabledIn)
+{
+}
-{}
-
IndexRange IndexConversionBufferMtl::getRangeForConvertedBuffer(size_t count)
{
return IndexRange{0, count};
@@ -403,6 +401,7 @@
buffer.convertedBuffer = nullptr;
buffer.convertedOffset = 0;
}
+ mRestartIndicesDirty = true;
}
void BufferMtl::clearConversionBuffers()
@@ -412,6 +411,53 @@
mUniformConversionBuffers.clear();
}
+template<typename T>
+static void calculateRestartRanges(ContextMtl* ctx, mtl::BufferRef idxBuffer, std::vector<IndexRange> * ranges)
+{
+ ranges->clear();
+ T *bufferData = (T*)(idxBuffer->mapReadOnly(ctx));
+ for(int i = 0; i < idxBuffer->size()/sizeof(T); i++)
+ {
+ T value = bufferData[i];
+ if(value == std::numeric_limits<T>::max())
+ {
+ IndexRange newRange;
+ newRange.restartBegin = i;
+ //Find the end of the restart range.
+ do
+ {
+ ++i;
+ value = bufferData[i];
+ }while (i < idxBuffer->size() && value == std::numeric_limits<T>::max());
+ newRange.restartEnd = i-1;
+ ranges->push_back(newRange);
+ }
+ }
+}
+
+const std::vector<IndexRange> & BufferMtl::getRestartIndices(ContextMtl * ctx, gl::DrawElementsType indexType)
+{
+ if(mRestartIndicesDirty)
+ {
+ switch(indexType)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ calculateRestartRanges<uint8_t>(ctx, getCurrentBuffer(),&mRestartIndices);
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ calculateRestartRanges<uint16_t>(ctx, getCurrentBuffer(),&mRestartIndices);
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ calculateRestartRanges<uint32_t>(ctx, getCurrentBuffer(),&mRestartIndices);
+ break;
+ default:
+ ASSERT(false);
+
+ }
+ mRestartIndicesDirty = false;
+ }
+ return mRestartIndices;
+}
angle::Result BufferMtl::setDataImpl(const gl::Context *context,
gl::BufferBinding target,
const void *data,
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.h (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.h 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.h 2021-04-25 19:17:10 UTC (rev 276569)
@@ -157,13 +157,6 @@
const GLint *baseVertices,
const GLuint *baseInstances,
GLsizei drawcount) override;
- angle::Result drawElementsSimpleTypesPrimitiveRestart(const gl::Context *context,
- gl::PrimitiveMode mode,
- GLsizei count,
- gl::DrawElementsType type,
- const void *indices,
- GLsizei instances);
-
// Device loss
gl::GraphicsResetStatus getResetStatus() override;
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.mm (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.mm 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.mm 2021-04-25 19:17:10 UTC (rev 276569)
@@ -579,59 +579,7 @@
return drawElementsInstanced(context, gl::PrimitiveMode::Lines, count, type, indices,
instances);
}
-angle::Result ContextMtl::drawElementsSimpleTypesPrimitiveRestart(const gl::Context *context,
- gl::PrimitiveMode mode,
- GLsizei count,
- gl::DrawElementsType type,
- const void *indices,
- GLsizei instances)
-{
- mtl::BufferRef genIdxBuffer;
- uint32_t genIdxBufferOffset;
- uint32_t reservedIndices = count;
- size_t genIndicesCount;
- ANGLE_TRY(AllocateBufferFromPool(this, reservedIndices, &mPrimitiveRestartBuffer, &genIdxBuffer,
- &genIdxBufferOffset));
- switch (mode)
- {
- case gl::PrimitiveMode::Points:
- ANGLE_TRY(getDisplay()->getUtils().generatePrimitiveRestartPointsBuffer(
- this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, true},
- &genIndicesCount));
- break;
- case gl::PrimitiveMode::Lines:
- ANGLE_TRY(getDisplay()->getUtils().generatePrimitiveRestartLinesBuffer(
- this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, true},
- &genIndicesCount));
- break;
- case gl::PrimitiveMode::Triangles:
- ANGLE_TRY(getDisplay()->getUtils().generatePrimitiveRestartTrianglesBuffer(
- this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, true},
- &genIndicesCount));
- break;
- default:
- UNREACHABLE();
- return angle::Result::Stop;
- }
- ANGLE_TRY(mPrimitiveRestartBuffer.commit(this));
- MTLPrimitiveType mtlType = mtl::GetPrimitiveType(mode);
- if (mState.isTransformFeedbackActiveUnpaused())
- {
- ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type,
- reinterpret_cast<const void *>(0), true));
-
- execDrawIndexedInstanced(mtlType, (uint32_t)genIndicesCount, MTLIndexTypeUInt32,
- genIdxBuffer, genIdxBufferOffset, instances);
- }
- ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, false));
-
- execDrawIndexedInstanced(mtlType, (uint32_t)genIndicesCount, MTLIndexTypeUInt32, genIdxBuffer,
- genIdxBufferOffset, instances);
-
- return angle::Result::Continue;
-}
-
angle::Result ContextMtl::drawElementsImpl(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei count,
@@ -657,12 +605,18 @@
mtl::BufferRef idxBuffer;
size_t convertedOffset = 0;
gl::DrawElementsType convertedType = type;
- ANGLE_TRY(mVertexArray->getIndexBuffer(context, type, mode, count, indices, &idxBuffer,
+ ANGLE_TRY(mVertexArray->getIndexBuffer(context, type, count, indices, &idxBuffer,
&convertedOffset, &convertedType));
ASSERT(idxBuffer);
ASSERT((convertedOffset % mtl::kIndexBufferOffsetAlignment) == 0);
uint32_t convertedCounti32 = (uint32_t)count;
+
+ //Draw commands will only be broken up if transform feedback is enabled,
+ //if the mode is a simple type, and if the buffer contained any restart
+ //indices.
+ const std::vector<DrawCommandRange> drawCommands = mVertexArray->getDrawIndices(context, type, convertedType, mode, convertedCounti32, convertedOffset);
+
if (mState.isTransformFeedbackActiveUnpaused())
{
ANGLE_TRY(setupDraw(context, mode, 0, convertedCounti32, instances, type, indices, true));
@@ -673,14 +627,21 @@
if (instances == 0)
{
// Normal draw
- mRenderEncoder.drawIndexed(mtlType, convertedCounti32, mtlIdxType, idxBuffer,
- convertedOffset);
+ for(auto & command : drawCommands)
+ {
+ mRenderEncoder.drawIndexed(mtlType, command.count, mtlIdxType, idxBuffer,
+ command.offset);
+
+ }
}
else
{
// Instanced draw
- execDrawIndexedInstanced(mtlType, convertedCounti32, mtlIdxType, idxBuffer,
- convertedOffset, instanceCount);
+ for(auto & command : drawCommands)
+ {
+ execDrawIndexedInstanced(mtlType, command.count, mtlIdxType, idxBuffer,
+ command.offset, instanceCount);
+ }
}
}
@@ -693,14 +654,20 @@
if (instances == 0)
{
// Normal draw
- mRenderEncoder.drawIndexed(mtlType, convertedCounti32, mtlIdxType, idxBuffer,
- convertedOffset);
+ for(auto & command : drawCommands)
+ {
+ mRenderEncoder.drawIndexed(mtlType, command.count, mtlIdxType, idxBuffer,
+ command.offset);
+ }
}
else
{
// Instanced draw
- execDrawIndexedInstanced(mtlType, convertedCounti32, mtlIdxType, idxBuffer, convertedOffset,
+ for(auto & command : drawCommands)
+ {
+ execDrawIndexedInstanced(mtlType, command.count, mtlIdxType, idxBuffer, command.offset,
instanceCount);
+ }
}
return angle::Result::Continue;
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.h (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.h 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.h 2021-04-25 19:17:10 UTC (rev 276569)
@@ -53,13 +53,20 @@
angle::Result getIndexBuffer(const gl::Context *glContext,
gl::DrawElementsType indexType,
- gl::PrimitiveMode primitiveMode,
size_t indexCount,
const void *sourcePointer,
mtl::BufferRef *idxBufferOut,
size_t *idxBufferOffsetOut,
gl::DrawElementsType *indexTypeOut);
-
+
+
+ std::vector<DrawCommandRange> getDrawIndices(const gl::Context *glContext,
+ gl::DrawElementsType originalIndexType,
+ gl::DrawElementsType indexType,
+ gl::PrimitiveMode primitiveMode,
+ uint32_t indexCount,
+ size_t offset);
+
// Use to emulate instanced draw for instance <instanceId>.
// The typical call sequence for emulated instance draw is:
// - setupDraw()
@@ -85,13 +92,11 @@
angle::Result convertIndexBuffer(const gl::Context *glContext,
gl::DrawElementsType indexType,
- gl::PrimitiveMode mode,
size_t offset,
mtl::BufferRef *idxBufferOut,
size_t *idxBufferOffsetOut);
angle::Result streamIndexBufferFromClient(const gl::Context *glContext,
gl::DrawElementsType indexType,
- gl::PrimitiveMode primitiveType,
size_t indexCount,
const void *sourcePointer,
mtl::BufferRef *idxBufferOut,
@@ -127,7 +132,7 @@
size_t vertexCount,
bool isExpandingComponents,
ConversionBufferMtl *conversion);
-
+
// These can point to real BufferMtl or converted buffer in mConvertedArrayBufferHolders
gl::AttribArray<BufferHolderMtl *> mCurrentArrayBuffers;
gl::AttribArray<SimpleWeakBufferHolderMtl> mConvertedArrayBufferHolders;
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.mm (276568 => 276569)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.mm 2021-04-25 19:16:23 UTC (rev 276568)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/VertexArrayMtl.mm 2021-04-25 19:17:10 UTC (rev 276569)
@@ -79,7 +79,6 @@
const uint8_t *sourcePointer,
gl::DrawElementsType indexType,
size_t indexCount,
- gl::PrimitiveMode mode,
bool primitiveRestartEnabled,
mtl::BufferRef *bufferOut,
size_t *bufferOffsetOut)
@@ -696,7 +695,6 @@
angle::Result VertexArrayMtl::getIndexBuffer(const gl::Context *context,
gl::DrawElementsType type,
- gl::PrimitiveMode mode,
size_t count,
const void *indices,
mtl::BufferRef *idxBufferOut,
@@ -708,7 +706,7 @@
size_t convertedOffset = reinterpret_cast<size_t>(indices);
if (!glElementArrayBuffer)
{
- ANGLE_TRY(streamIndexBufferFromClient(context, type, mode, count, indices, idxBufferOut,
+ ANGLE_TRY(streamIndexBufferFromClient(context, type, count, indices, idxBufferOut,
idxBufferOffsetOut));
}
else
@@ -717,7 +715,7 @@
(convertedOffset % mtl::kIndexBufferOffsetAlignment) != 0;
if (needConversion)
{
- ANGLE_TRY(convertIndexBuffer(context, type, mode, convertedOffset, idxBufferOut,
+ ANGLE_TRY(convertIndexBuffer(context, type, convertedOffset, idxBufferOut,
idxBufferOffsetOut));
}
else
@@ -739,9 +737,99 @@
return angle::Result::Continue;
}
+std::vector<DrawCommandRange> VertexArrayMtl::getDrawIndices(const gl::Context *glContext,
+ gl::DrawElementsType originalIndexType,
+ gl::DrawElementsType indexType,
+ gl::PrimitiveMode primitiveMode,
+ uint32_t indexCount,
+ size_t offset)
+{
+ ContextMtl *contextMtl = mtl::GetImpl(glContext);
+ std::vector<DrawCommandRange> drawCommands;
+
+ BufferMtl *idxBuffer = mtl::GetImpl(getState().getElementArrayBuffer());
+ const std::vector<IndexRange> restartIndices = idxBuffer->getRestartIndices(contextMtl, originalIndexType);
+ bool isSimpleType =
+ primitiveMode == gl::PrimitiveMode::Points ||
+ primitiveMode == gl::PrimitiveMode::Lines ||
+ primitiveMode == gl::PrimitiveMode::Triangles;
+ //If prim restart isn't enabled, or we're drawing a restartable type, or there's no restarts, skip breaking up draw commands.
+ if(restartIndices.size() == 0 || !isSimpleType || !glContext->getState().isPrimitiveRestartEnabled())
+ {
+ drawCommands.push_back({indexCount, offset});
+ return drawCommands;
+ }
+ else
+ {
+ //Reminder, offset is in bytes, not elements.
+ //Slice draw commands based off of indices.
+ int nIndicesPerPrimitive;
+ switch(primitiveMode)
+ {
+ case gl::PrimitiveMode::Points:
+ nIndicesPerPrimitive = 1;
+ break;
+ case gl::PrimitiveMode::Lines:
+ nIndicesPerPrimitive = 2;
+ break;
+ case gl::PrimitiveMode::Triangles:
+ nIndicesPerPrimitive = 3;
+ break;
+ default:
+ //Unreachable
+ ASSERT(FALSE);
+ return drawCommands;
+ }
+ const GLuint indexTypeBytes = gl::GetDrawElementsTypeSize(indexType);
+ uint32_t indicesLeft = indexCount;
+ size_t currentIndexOffset = offset / indexTypeBytes;
+
+ for(auto & range : restartIndices)
+ {
+ if(range.restartBegin > currentIndexOffset)
+ {
+ int64_t nIndicesInSlice = ((int64_t)range.restartBegin - currentIndexOffset) - ((int64_t) range.restartBegin - currentIndexOffset) % nIndicesPerPrimitive;
+ size_t restartSize = (range.restartEnd - range.restartBegin) + 1;
+ if(nIndicesInSlice > nIndicesPerPrimitive)
+ drawCommands.push_back({(uint32_t)nIndicesInSlice, currentIndexOffset * indexTypeBytes});
+ //Account for dropped indices due to incomplete primitives.
+ size_t indicesUsed = ( (range.restartBegin + restartSize) - currentIndexOffset);
+ if(indicesLeft <= indicesUsed)
+ {
+ indicesLeft = 0;
+ }
+ else
+ {
+ indicesLeft -= indicesUsed;
+ }
+ currentIndexOffset = (size_t)(range.restartBegin + restartSize);
+ }
+ //If the initial offset into the index buffer is within a restart zone, move to the end of the restart zone.
+ else if(range.restartEnd >= currentIndexOffset)
+ {
+ size_t restartSize = (range.restartEnd - currentIndexOffset) + 1;
+ if(indicesLeft <= restartSize)
+ {
+ indicesLeft = 0;
+ }
+ else
+ {
+ indicesLeft -= restartSize;
+ }
+ currentIndexOffset = (size_t)(currentIndexOffset + restartSize);
+ }
+
+ }
+ if(indicesLeft >= nIndicesPerPrimitive)
+ drawCommands.push_back({indicesLeft, currentIndexOffset * indexTypeBytes});
+ return drawCommands;
+ }
+
+}
+
+
angle::Result VertexArrayMtl::convertIndexBuffer(const gl::Context *glContext,
gl::DrawElementsType indexType,
- gl::PrimitiveMode mode,
size_t offset,
mtl::BufferRef *idxBufferOut,
size_t *idxBufferOffsetOut)
@@ -779,7 +867,7 @@
// We shouldn't use GPU to convert when we are in a middle of a render pass.
ANGLE_TRY(StreamIndexData(contextMtl, &conversion->data,
idxBuffer->getClientShadowCopyData(contextMtl) + offsetModulo,
- indexType, indexCount, mode, glState.isPrimitiveRestartEnabled(),
+ indexType, indexCount, glState.isPrimitiveRestartEnabled(),
&conversion->convertedBuffer, &conversion->convertedOffset));
}
else
@@ -787,7 +875,7 @@
ANGLE_TRY(convertIndexBufferGPU(glContext, indexType, idxBuffer, offsetModulo, indexCount,
conversion));
}
-
+ //Calculate ranges for prim restart simple types.
*idxBufferOut = conversion->convertedBuffer;
*idxBufferOffsetOut = conversion->convertedOffset + alignedOffset;
@@ -829,7 +917,6 @@
angle::Result VertexArrayMtl::streamIndexBufferFromClient(const gl::Context *context,
gl::DrawElementsType indexType,
- gl::PrimitiveMode mode,
size_t indexCount,
const void *sourcePointer,
mtl::BufferRef *idxBufferOut,
@@ -839,7 +926,7 @@
ContextMtl *contextMtl = mtl::GetImpl(context);
auto srcData = static_cast<const uint8_t *>(sourcePointer);
- ANGLE_TRY(StreamIndexData(contextMtl, &mDynamicIndexData, srcData, indexType, indexCount, mode,
+ ANGLE_TRY(StreamIndexData(contextMtl, &mDynamicIndexData, srcData, indexType, indexCount,
context->getState().isPrimitiveRestartEnabled(), idxBufferOut,
idxBufferOffsetOut));