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 ...@@ -276,15 +276,36 @@ class ContextMtl : public ContextImpl, public mtl::Context
const void *indices, const void *indices,
mtl::BufferRef *lastSegmentIndexBufferOut); 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, angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context,
GLint first, GLint first,
GLsizei count); GLsizei count,
angle::Result drawTriFanArraysLegacy(const gl::Context *context, GLint first, GLsizei count); GLsizei instances);
angle::Result drawTriFanArraysLegacy(const gl::Context *context,
GLint first,
GLsizei count,
GLsizei instances);
angle::Result drawTriFanElements(const gl::Context *context, angle::Result drawTriFanElements(const gl::Context *context,
GLsizei count, GLsizei count,
gl::DrawElementsType type, 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, void updateViewport(FramebufferMtl *framebufferMtl,
const gl::Rectangle &viewport, const gl::Rectangle &viewport,
......
...@@ -572,9 +572,8 @@ void DisplayMtl::initializeExtensions() const ...@@ -572,9 +572,8 @@ void DisplayMtl::initializeExtensions() const
mNativeExtensions.semaphore = false; mNativeExtensions.semaphore = false;
mNativeExtensions.semaphoreFd = false; mNativeExtensions.semaphoreFd = false;
// TODO: Enable this always and emulate instanced draws if any divisor exceeds the maximum mNativeExtensions.instancedArraysANGLE = mFeatures.hasBaseVertexInstancedDraw.enabled;
// supported. http://anglebug.com/2672 mNativeExtensions.instancedArraysEXT = mNativeExtensions.instancedArraysANGLE;
mNativeExtensions.instancedArraysANGLE = false;
mNativeExtensions.robustBufferAccessBehavior = false; mNativeExtensions.robustBufferAccessBehavior = false;
......
...@@ -264,6 +264,7 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, ...@@ -264,6 +264,7 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
mVertexArrayDirty = false; mVertexArrayDirty = false;
const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes(); const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes();
const std::vector<gl::VertexBinding> &bindings = mState.getVertexBindings();
mtl::VertexDesc &desc = *vertexDescOut; mtl::VertexDesc &desc = *vertexDescOut;
...@@ -278,7 +279,8 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, ...@@ -278,7 +279,8 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
for (uint32_t v = 0; v < mtl::kMaxVertexAttribs; ++v) 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].offset = mCurrentArrayBufferOffsets[v];
desc.attributes[v].format = mCurrentArrayBufferFormats[v]; desc.attributes[v].format = mCurrentArrayBufferFormats[v];
...@@ -296,9 +298,17 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, ...@@ -296,9 +298,17 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
desc.attributes[v].bufferIndex = bufferIdx; desc.attributes[v].bufferIndex = bufferIdx;
ASSERT(bufferIdx < mtl::kMaxVertexAttribs); ASSERT(bufferIdx < mtl::kMaxVertexAttribs);
desc.layouts[bufferIdx].stepFunction = MTLVertexStepFunctionPerVertex; if (binding.getDivisor() == 0)
desc.layouts[bufferIdx].stepRate = 1; {
desc.layouts[bufferIdx].stride = mCurrentArrayBufferStrides[v]; 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, cmdEncoder->setVertexBuffer(mCurrentArrayBuffers[v]->getCurrentBuffer(glContext), 0,
bufferIdx); bufferIdx);
...@@ -351,32 +361,35 @@ angle::Result VertexArrayMtl::updateClientAttribs(const gl::Context *context, ...@@ -351,32 +361,35 @@ angle::Result VertexArrayMtl::updateClientAttribs(const gl::Context *context,
const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer); const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer);
ASSERT(src); ASSERT(src);
if (binding.getDivisor() > 0) GLint startElement;
size_t elementCount;
if (binding.getDivisor() == 0)
{ {
ANGLE_UNUSED_VARIABLE(instanceCount); // Per vertex attribute
// NOTE(hqle): support ES 3.0. startElement = startVertex;
// instanced attrib elementCount = vertexCount;
UNREACHABLE();
} }
else else
{ {
// Allocate space for startVertex + vertexCount so indexing will work. If we don't // Per instance attribute
// start at zero all the indices will be off. startElement = 0;
// Only vertexCount vertices will be used by the upcoming draw so that is all we copy. elementCount = UnsignedCeilDivide(instanceCount, binding.getDivisor());
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;
} }
// 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; mVertexArrayDirty = true;
......
...@@ -218,17 +218,28 @@ class RenderCommandEncoder final : public CommandEncoder ...@@ -218,17 +218,28 @@ class RenderCommandEncoder final : public CommandEncoder
RenderCommandEncoder &draw(MTLPrimitiveType primitiveType, RenderCommandEncoder &draw(MTLPrimitiveType primitiveType,
uint32_t vertexStart, uint32_t vertexStart,
uint32_t vertexCount); uint32_t vertexCount);
RenderCommandEncoder &drawInstanced(MTLPrimitiveType primitiveType,
uint32_t vertexStart,
uint32_t vertexCount,
uint32_t instances);
RenderCommandEncoder &drawIndexed(MTLPrimitiveType primitiveType, RenderCommandEncoder &drawIndexed(MTLPrimitiveType primitiveType,
uint32_t indexCount, uint32_t indexCount,
MTLIndexType indexType, MTLIndexType indexType,
const BufferRef &indexBuffer, const BufferRef &indexBuffer,
size_t bufferOffset); size_t bufferOffset);
RenderCommandEncoder &drawIndexedBaseVertex(MTLPrimitiveType primitiveType, RenderCommandEncoder &drawIndexedInstanced(MTLPrimitiveType primitiveType,
uint32_t indexCount, uint32_t indexCount,
MTLIndexType indexType, MTLIndexType indexType,
const BufferRef &indexBuffer, const BufferRef &indexBuffer,
size_t bufferOffset, size_t bufferOffset,
uint32_t baseVertex); 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); RenderCommandEncoder &setColorStoreAction(MTLStoreAction action, uint32_t colorAttachmentIndex);
// Set store action for every color attachment. // Set store action for every color attachment.
......
...@@ -673,6 +673,20 @@ RenderCommandEncoder &RenderCommandEncoder::draw(MTLPrimitiveType primitiveType, ...@@ -673,6 +673,20 @@ RenderCommandEncoder &RenderCommandEncoder::draw(MTLPrimitiveType primitiveType,
return *this; 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, RenderCommandEncoder &RenderCommandEncoder::drawIndexed(MTLPrimitiveType primitiveType,
uint32_t indexCount, uint32_t indexCount,
MTLIndexType indexType, MTLIndexType indexType,
...@@ -694,12 +708,37 @@ RenderCommandEncoder &RenderCommandEncoder::drawIndexed(MTLPrimitiveType primiti ...@@ -694,12 +708,37 @@ RenderCommandEncoder &RenderCommandEncoder::drawIndexed(MTLPrimitiveType primiti
return *this; return *this;
} }
RenderCommandEncoder &RenderCommandEncoder::drawIndexedBaseVertex(MTLPrimitiveType primitiveType, RenderCommandEncoder &RenderCommandEncoder::drawIndexedInstanced(MTLPrimitiveType primitiveType,
uint32_t indexCount, uint32_t indexCount,
MTLIndexType indexType, MTLIndexType indexType,
const BufferRef &indexBuffer, const BufferRef &indexBuffer,
size_t bufferOffset, size_t bufferOffset,
uint32_t baseVertex) 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) if (!indexBuffer)
{ {
...@@ -712,7 +751,7 @@ RenderCommandEncoder &RenderCommandEncoder::drawIndexedBaseVertex(MTLPrimitiveTy ...@@ -712,7 +751,7 @@ RenderCommandEncoder &RenderCommandEncoder::drawIndexedBaseVertex(MTLPrimitiveTy
indexType:indexType indexType:indexType
indexBuffer:indexBuffer->get() indexBuffer:indexBuffer->get()
indexBufferOffset:bufferOffset indexBufferOffset:bufferOffset
instanceCount:1 instanceCount:instances
baseVertex:baseVertex baseVertex:baseVertex
baseInstance:0]; baseInstance:0];
......
...@@ -407,6 +407,9 @@ angle::Result Buffer::reset(ContextMtl *context, size_t size, const uint8_t *dat ...@@ -407,6 +407,9 @@ angle::Result Buffer::reset(ContextMtl *context, size_t size, const uint8_t *dat
id<MTLDevice> metalDevice = context->getMetalDevice(); id<MTLDevice> metalDevice = context->getMetalDevice();
options = 0; options = 0;
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
options |= MTLResourceStorageModeManaged;
#endif
if (data) if (data)
{ {
...@@ -439,7 +442,12 @@ uint8_t *Buffer::map(ContextMtl *context) ...@@ -439,7 +442,12 @@ uint8_t *Buffer::map(ContextMtl *context)
return reinterpret_cast<uint8_t *>([get() contents]); 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 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