Skip to content
Permalink
Browse files
ANGLE Metal primitive restart range computation should not be done un…
…less primitive restart is enabled

https://bugs.webkit.org/show_bug.cgi?id=227452

Patch by Kimmo Kinnunen <kkinnunen@apple.com> on 2021-06-29
Reviewed by Kenneth Russell.

Primitive restart needs to scan the whole index buffer for values.
This should not be done unless needed.

* src/libANGLE/renderer/metal/VertexArrayMtl.mm:
(rx::VertexArrayMtl::getDrawIndices):
First check for primitive restart enabledness.
Compute the primitive restart values after this.
The algoritm should succeed when the count of primitive
restart ranges is zero, and it does not do much of work.
Use the restart range vector as reference, so that no copy
would be done.
Add spaces the if statements, comments and references.
Move the else arm of the if statement with return statement
to body of the function to reduce nesting.

Canonical link: https://commits.webkit.org/239238@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@279372 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
kkinnunen-apple authored and webkit-commit-queue committed Jun 29, 2021
1 parent c5198ef commit 3011fc4aa43e24b644be6c68174c0207031c8bc0
Showing 2 changed files with 80 additions and 62 deletions.
@@ -1,3 +1,25 @@
2021-06-29 Kimmo Kinnunen <kkinnunen@apple.com>

ANGLE Metal primitive restart range computation should not be done unless primitive restart is enabled
https://bugs.webkit.org/show_bug.cgi?id=227452

Reviewed by Kenneth Russell.

Primitive restart needs to scan the whole index buffer for values.
This should not be done unless needed.

* src/libANGLE/renderer/metal/VertexArrayMtl.mm:
(rx::VertexArrayMtl::getDrawIndices):
First check for primitive restart enabledness.
Compute the primitive restart values after this.
The algoritm should succeed when the count of primitive
restart ranges is zero, and it does not do much of work.
Use the restart range vector as reference, so that no copy
would be done.
Add spaces the if statements, comments and references.
Move the else arm of the if statement with return statement
to body of the function to reduce nesting.

2021-06-28 Kimmo Kinnunen <kkinnunen@apple.com>

iPhone 6S - iOS 15.0 - unable to retrieve WebGL2 context
@@ -744,87 +744,83 @@ inline void SetDefaultVertexBufferLayout(mtl::VertexBufferLayoutDesc *layout)
uint32_t indexCount,
size_t offset)
{
ContextMtl *contextMtl = mtl::GetImpl(glContext);
ContextMtl *contextMtl = mtl::GetImpl(glContext);
std::vector<DrawCommandRange> drawCommands;

BufferMtl *idxBuffer = mtl::GetImpl(getState().getElementArrayBuffer());
const std::vector<IndexRange> restartIndices = idxBuffer->getRestartIndices(contextMtl, originalIndexType);
// The indexed draw needs to be split to separate draw commands in case primitive restart is enabled
// and the drawn primitive supports primitive restart. Otherwise the whole indexed draw can be sent
// as one draw command.
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())
if (!isSimpleType || !glContext->getState().isPrimitiveRestartEnabled())
{
drawCommands.push_back({indexCount, offset});
return drawCommands;
}
else

BufferMtl *idxBuffer = mtl::GetImpl(getState().getElementArrayBuffer());
const std::vector<IndexRange> &restartIndices = idxBuffer->getRestartIndices(contextMtl, originalIndexType);
// Reminder, offset is in bytes, not elements.
// Slice draw commands based off of indices.
int nIndicesPerPrimitive;
switch (primitiveMode)
{
//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();
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)
{
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;
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);
}
const GLuint indexTypeBytes = gl::GetDrawElementsTypeSize(indexType);
uint32_t indicesLeft = indexCount;
size_t currentIndexOffset = offset / indexTypeBytes;

for(auto & range : restartIndices)
// 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)
{
if(range.restartBegin > currentIndexOffset)
size_t restartSize = (range.restartEnd - currentIndexOffset) + 1;
if (indicesLeft <= restartSize)
{
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);
indicesLeft = 0;
}
//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)
else
{
size_t restartSize = (range.restartEnd - currentIndexOffset) + 1;
if(indicesLeft <= restartSize)
{
indicesLeft = 0;
}
else
{
indicesLeft -= restartSize;
}
currentIndexOffset = (size_t)(currentIndexOffset + restartSize);
indicesLeft -= restartSize;
}

currentIndexOffset = (size_t)(currentIndexOffset + restartSize);
}
if(indicesLeft >= nIndicesPerPrimitive)
drawCommands.push_back({indicesLeft, currentIndexOffset * indexTypeBytes});
return drawCommands;
}

if (indicesLeft >= nIndicesPerPrimitive)
drawCommands.push_back({indicesLeft, currentIndexOffset * indexTypeBytes});
return drawCommands;
}


0 comments on commit 3011fc4

Please sign in to comment.