Commit e5b474c6 by Le Hoang Quyen Committed by Commit Bot

Metal: support ANGLE_instance_arrays/EXT_instance_arrays

Also added TRIANGLE_FAN & LINE_LOOP instanced draws test cases. Bug: angleproject:2634 Change-Id: I84740a7221ab49710cf23767c81fa2d303aad364 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1919280Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 34e5a96e
......@@ -276,15 +276,36 @@ class ContextMtl : public ContextImpl, public mtl::Context
const void *indices,
mtl::BufferRef *lastSegmentIndexBufferOut);
angle::Result drawTriFanArrays(const gl::Context *context, GLint first, GLsizei count);
angle::Result drawTriFanArrays(const gl::Context *context,
GLint first,
GLsizei count,
GLsizei instances);
angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context,
GLint first,
GLsizei count);
angle::Result drawTriFanArraysLegacy(const gl::Context *context, GLint first, GLsizei count);
GLsizei count,
GLsizei instances);
angle::Result drawTriFanArraysLegacy(const gl::Context *context,
GLint first,
GLsizei count,
GLsizei instances);
angle::Result drawTriFanElements(const gl::Context *context,
GLsizei count,
gl::DrawElementsType type,
const void *indices);
const void *indices,
GLsizei instances);
angle::Result drawArraysImpl(const gl::Context *context,
gl::PrimitiveMode mode,
GLint first,
GLsizei count,
GLsizei instanceCount);
angle::Result drawElementsImpl(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei count,
gl::DrawElementsType type,
const void *indices,
GLsizei instanceCount);
void updateViewport(FramebufferMtl *framebufferMtl,
const gl::Rectangle &viewport,
......
......@@ -572,9 +572,8 @@ void DisplayMtl::initializeExtensions() const
mNativeExtensions.semaphore = false;
mNativeExtensions.semaphoreFd = false;
// TODO: Enable this always and emulate instanced draws if any divisor exceeds the maximum
// supported. http://anglebug.com/2672
mNativeExtensions.instancedArraysANGLE = false;
mNativeExtensions.instancedArraysANGLE = mFeatures.hasBaseVertexInstancedDraw.enabled;
mNativeExtensions.instancedArraysEXT = mNativeExtensions.instancedArraysANGLE;
mNativeExtensions.robustBufferAccessBehavior = false;
......
......@@ -264,6 +264,7 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
mVertexArrayDirty = false;
const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes();
const std::vector<gl::VertexBinding> &bindings = mState.getVertexBindings();
mtl::VertexDesc &desc = *vertexDescOut;
......@@ -278,7 +279,8 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
for (uint32_t v = 0; v < mtl::kMaxVertexAttribs; ++v)
{
const auto &attrib = attribs[v];
const auto &attrib = attribs[v];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
desc.attributes[v].offset = mCurrentArrayBufferOffsets[v];
desc.attributes[v].format = mCurrentArrayBufferFormats[v];
......@@ -296,9 +298,17 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
desc.attributes[v].bufferIndex = bufferIdx;
ASSERT(bufferIdx < mtl::kMaxVertexAttribs);
desc.layouts[bufferIdx].stepFunction = MTLVertexStepFunctionPerVertex;
desc.layouts[bufferIdx].stepRate = 1;
desc.layouts[bufferIdx].stride = mCurrentArrayBufferStrides[v];
if (binding.getDivisor() == 0)
{
desc.layouts[bufferIdx].stepFunction = MTLVertexStepFunctionPerVertex;
desc.layouts[bufferIdx].stepRate = 1;
}
else
{
desc.layouts[bufferIdx].stepFunction = MTLVertexStepFunctionPerInstance;
desc.layouts[bufferIdx].stepRate = binding.getDivisor();
}
desc.layouts[bufferIdx].stride = mCurrentArrayBufferStrides[v];
cmdEncoder->setVertexBuffer(mCurrentArrayBuffers[v]->getCurrentBuffer(glContext), 0,
bufferIdx);
......@@ -351,32 +361,35 @@ angle::Result VertexArrayMtl::updateClientAttribs(const gl::Context *context,
const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer);
ASSERT(src);
if (binding.getDivisor() > 0)
GLint startElement;
size_t elementCount;
if (binding.getDivisor() == 0)
{
ANGLE_UNUSED_VARIABLE(instanceCount);
// NOTE(hqle): support ES 3.0.
// instanced attrib
UNREACHABLE();
// Per vertex attribute
startElement = startVertex;
elementCount = vertexCount;
}
else
{
// Allocate space for startVertex + vertexCount so indexing will work. If we don't
// start at zero all the indices will be off.
// Only vertexCount vertices will be used by the upcoming draw so that is all we copy.
size_t bytesToAllocate = (startVertex + vertexCount) * stride;
src += startVertex * binding.getStride();
size_t destOffset = startVertex * stride;
ANGLE_TRY(StreamVertexData(contextMtl, &mDynamicVertexData, src, bytesToAllocate,
destOffset, vertexCount, binding.getStride(),
vertexFormat.vertexLoadFunction,
&mConvertedArrayBufferHolders[attribIndex],
&mCurrentArrayBufferOffsets[attribIndex]));
mCurrentArrayBuffers[attribIndex] = &mConvertedArrayBufferHolders[attribIndex];
mCurrentArrayBufferFormats[attribIndex] = vertexFormat.metalFormat;
mCurrentArrayBufferStrides[attribIndex] = stride;
// Per instance attribute
startElement = 0;
elementCount = UnsignedCeilDivide(instanceCount, binding.getDivisor());
}
// Allocate space for startElement + elementCount so indexing will work. If we don't
// start at zero all the indices will be off.
// Only elementCount vertices will be used by the upcoming draw so that is all we copy.
size_t bytesToAllocate = (startElement + elementCount) * stride;
src += startElement * binding.getStride();
size_t destOffset = startElement * stride;
ANGLE_TRY(StreamVertexData(
contextMtl, &mDynamicVertexData, src, bytesToAllocate, destOffset, elementCount,
binding.getStride(), vertexFormat.vertexLoadFunction,
&mConvertedArrayBufferHolders[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
mCurrentArrayBuffers[attribIndex] = &mConvertedArrayBufferHolders[attribIndex];
mCurrentArrayBufferFormats[attribIndex] = vertexFormat.metalFormat;
mCurrentArrayBufferStrides[attribIndex] = stride;
}
mVertexArrayDirty = true;
......
......@@ -218,17 +218,28 @@ class RenderCommandEncoder final : public CommandEncoder
RenderCommandEncoder &draw(MTLPrimitiveType primitiveType,
uint32_t vertexStart,
uint32_t vertexCount);
RenderCommandEncoder &drawInstanced(MTLPrimitiveType primitiveType,
uint32_t vertexStart,
uint32_t vertexCount,
uint32_t instances);
RenderCommandEncoder &drawIndexed(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset);
RenderCommandEncoder &drawIndexedBaseVertex(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset,
uint32_t baseVertex);
RenderCommandEncoder &drawIndexedInstanced(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset,
uint32_t instances);
RenderCommandEncoder &drawIndexedInstancedBaseVertex(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset,
uint32_t instances,
uint32_t baseVertex);
RenderCommandEncoder &setColorStoreAction(MTLStoreAction action, uint32_t colorAttachmentIndex);
// Set store action for every color attachment.
......
......@@ -673,6 +673,20 @@ RenderCommandEncoder &RenderCommandEncoder::draw(MTLPrimitiveType primitiveType,
return *this;
}
RenderCommandEncoder &RenderCommandEncoder::drawInstanced(MTLPrimitiveType primitiveType,
uint32_t vertexStart,
uint32_t vertexCount,
uint32_t instances)
{
[get() drawPrimitives:primitiveType
vertexStart:vertexStart
vertexCount:vertexCount
instanceCount:instances];
return *this;
}
RenderCommandEncoder &RenderCommandEncoder::drawIndexed(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
......@@ -694,12 +708,37 @@ RenderCommandEncoder &RenderCommandEncoder::drawIndexed(MTLPrimitiveType primiti
return *this;
}
RenderCommandEncoder &RenderCommandEncoder::drawIndexedBaseVertex(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset,
uint32_t baseVertex)
RenderCommandEncoder &RenderCommandEncoder::drawIndexedInstanced(MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset,
uint32_t instances)
{
if (!indexBuffer)
{
return *this;
}
cmdBuffer().setReadDependency(indexBuffer);
[get() drawIndexedPrimitives:primitiveType
indexCount:indexCount
indexType:indexType
indexBuffer:indexBuffer->get()
indexBufferOffset:bufferOffset
instanceCount:instances];
return *this;
}
RenderCommandEncoder &RenderCommandEncoder::drawIndexedInstancedBaseVertex(
MTLPrimitiveType primitiveType,
uint32_t indexCount,
MTLIndexType indexType,
const BufferRef &indexBuffer,
size_t bufferOffset,
uint32_t instances,
uint32_t baseVertex)
{
if (!indexBuffer)
{
......@@ -712,7 +751,7 @@ RenderCommandEncoder &RenderCommandEncoder::drawIndexedBaseVertex(MTLPrimitiveTy
indexType:indexType
indexBuffer:indexBuffer->get()
indexBufferOffset:bufferOffset
instanceCount:1
instanceCount:instances
baseVertex:baseVertex
baseInstance:0];
......
......@@ -407,6 +407,9 @@ angle::Result Buffer::reset(ContextMtl *context, size_t size, const uint8_t *dat
id<MTLDevice> metalDevice = context->getMetalDevice();
options = 0;
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
options |= MTLResourceStorageModeManaged;
#endif
if (data)
{
......@@ -439,7 +442,12 @@ uint8_t *Buffer::map(ContextMtl *context)
return reinterpret_cast<uint8_t *>([get() contents]);
}
void Buffer::unmap(ContextMtl *context) {}
void Buffer::unmap(ContextMtl *context)
{
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
[get() didModifyRange:NSMakeRange(0, size())];
#endif
}
size_t Buffer::size() const
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment