Skip to content

Commit

Permalink
WebGPU: Sync index buffers, add indexed draw calls
Browse files Browse the repository at this point in the history
Bug: angleproject:368600230
Change-Id: Ibf1c4921635b525b7650e70ce7dc939e2bad2ebb
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5828229
Reviewed-by: Liza Burakova <[email protected]>
Commit-Queue: Geoff Lang <[email protected]>
Reviewed-by: Shahbaz Youssefi <[email protected]>
  • Loading branch information
vonture authored and Angle LUCI CQ committed Sep 24, 2024
1 parent 75297ee commit 0b61071
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 36 deletions.
124 changes: 97 additions & 27 deletions src/libANGLE/renderer/wgpu/ContextWgpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ContextWgpu::ContextWgpu(const gl::State &state, gl::ErrorSet *errorSet, Display
DIRTY_BIT_VIEWPORT,
DIRTY_BIT_SCISSOR,
DIRTY_BIT_VERTEX_BUFFERS,
DIRTY_BIT_INDEX_BUFFER,
};
}

Expand Down Expand Up @@ -156,6 +157,11 @@ void ContextWgpu::invalidateVertexBuffers()
mDirtyVertexBuffers = mCurrentRenderPipelineAllAttributes;
}

void ContextWgpu::invalidateIndexBuffer()
{
mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
}

angle::Result ContextWgpu::finish(const gl::Context *context)
{
ANGLE_TRY(flush(webgpu::RenderPassClosureReason::GLFinish));
Expand Down Expand Up @@ -184,8 +190,8 @@ angle::Result ContextWgpu::drawArrays(const gl::Context *context,
return angle::Result::Continue;
}

ANGLE_TRY(
setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, nullptr));
ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, nullptr,
nullptr));
mCommandBuffer.draw(static_cast<uint32_t>(count), 1, static_cast<uint32_t>(first), 0);
return angle::Result::Continue;
}
Expand All @@ -208,7 +214,7 @@ angle::Result ContextWgpu::drawArraysInstanced(const gl::Context *context,
}

ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount,
gl::DrawElementsType::InvalidEnum, nullptr));
gl::DrawElementsType::InvalidEnum, nullptr, nullptr));
mCommandBuffer.draw(static_cast<uint32_t>(count), static_cast<uint32_t>(instanceCount),
static_cast<uint32_t>(first), 0);
return angle::Result::Continue;
Expand All @@ -233,7 +239,7 @@ angle::Result ContextWgpu::drawArraysInstancedBaseInstance(const gl::Context *co
}

ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount,
gl::DrawElementsType::InvalidEnum, nullptr));
gl::DrawElementsType::InvalidEnum, nullptr, nullptr));
mCommandBuffer.draw(static_cast<uint32_t>(count), static_cast<uint32_t>(instanceCount),
static_cast<uint32_t>(first), baseInstance);
return angle::Result::Continue;
Expand All @@ -256,8 +262,9 @@ angle::Result ContextWgpu::drawElements(const gl::Context *context,
return angle::Result::Continue;
}

ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
// TODO: draw
uint32_t firstVertex = 0;
ANGLE_TRY(setupDraw(context, mode, 0, count, 1, type, indices, &firstVertex));
mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), 1, firstVertex, 0, 0);
return angle::Result::Continue;
}

Expand All @@ -279,8 +286,10 @@ angle::Result ContextWgpu::drawElementsBaseVertex(const gl::Context *context,
return angle::Result::Continue;
}

ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
// TODO: draw
uint32_t firstVertex = 0;
ANGLE_TRY(setupDraw(context, mode, 0, count, 1, type, indices, &firstVertex));
mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), 1, firstVertex,
static_cast<uint32_t>(baseVertex), 0);
return angle::Result::Continue;
}

Expand All @@ -302,8 +311,10 @@ angle::Result ContextWgpu::drawElementsInstanced(const gl::Context *context,
return angle::Result::Continue;
}

ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
// TODO: draw
uint32_t firstVertex = 0;
ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, &firstVertex));
mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), static_cast<uint32_t>(instances),
firstVertex, 0, 0);
return angle::Result::Continue;
}

Expand All @@ -326,8 +337,10 @@ angle::Result ContextWgpu::drawElementsInstancedBaseVertex(const gl::Context *co
return angle::Result::Continue;
}

ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
// TODO: draw
uint32_t firstVertex = 0;
ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, &firstVertex));
mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), static_cast<uint32_t>(instances),
firstVertex, static_cast<uint32_t>(baseVertex), 0);
return angle::Result::Continue;
}

Expand All @@ -351,8 +364,11 @@ angle::Result ContextWgpu::drawElementsInstancedBaseVertexBaseInstance(const gl:
return angle::Result::Continue;
}

ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
// TODO: draw
uint32_t firstVertex = 0;
ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, &firstVertex));
mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), static_cast<uint32_t>(instances),
firstVertex, static_cast<uint32_t>(baseVertex),
static_cast<uint32_t>(baseInstance));
return angle::Result::Continue;
}

Expand Down Expand Up @@ -982,31 +998,44 @@ angle::Result ContextWgpu::endRenderPass(webgpu::RenderPassClosureReason closure
return angle::Result::Continue;
}

angle::Result ContextWgpu::setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei indexCount,
GLsizei instanceCount,
gl::DrawElementsType indexType,
const void *indices)
{
// TODO: handle index buffer binding

return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices);
}

angle::Result ContextWgpu::setupDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLint firstVertexOrInvalid,
GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices)
const void *indices,
uint32_t *outFirstIndex)
{
if (mRenderPipelineDesc.setPrimitiveMode(mode, indexTypeOrInvalid))
{
invalidateCurrentRenderPipeline();
}

const void *adjustedIndicesPtr = indices;
if (mState.areClientArraysEnabled())
{
VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
ANGLE_TRY(vertexArrayWgpu->syncClientArrays(
context, mState.getProgramExecutable()->getActiveAttribLocationsMask(),
firstVertexOrInvalid, vertexOrIndexCount, indexTypeOrInvalid, indices, instanceCount,
mState.isPrimitiveRestartEnabled(), &adjustedIndicesPtr));
}

bool reAddDirtyIndexBufferBit = false;
if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
{
*outFirstIndex = gl_wgpu::GetFirstIndexForDrawCall(indexTypeOrInvalid, adjustedIndicesPtr);
if (mCurrentIndexBufferType != indexTypeOrInvalid)
{
invalidateIndexBuffer();
}
}
else
{
ASSERT(outFirstIndex == nullptr);
}

if (mDirtyBits.any())
{
for (DirtyBits::Iterator dirtyBitIter = mDirtyBits.begin();
Expand Down Expand Up @@ -1040,12 +1069,31 @@ angle::Result ContextWgpu::setupDraw(const gl::Context *context,
mDirtyVertexBuffers.reset();
break;

case DIRTY_BIT_INDEX_BUFFER:
if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
{
ANGLE_TRY(handleDirtyIndexBuffer(indexTypeOrInvalid, &dirtyBitIter));
}
else
{
// If this is not an indexed draw call, don't sync the index buffer. Save it
// for a future indexed draw call when we know what index type to use
reAddDirtyIndexBufferBit = true;
}
break;

default:
UNREACHABLE();
break;
}
}

if (reAddDirtyIndexBufferBit)
{
// Re-add the index buffer dirty bit for a future indexed draw call.
mDirtyBits.reset(DIRTY_BIT_INDEX_BUFFER);
}

mDirtyBits.reset();
}

Expand Down Expand Up @@ -1166,6 +1214,8 @@ angle::Result ContextWgpu::handleDirtyVertexBuffers(const gl::AttributesMask &sl
webgpu::BufferHelper *buffer = vertexArrayWgpu->getVertexBuffer(slot);
if (!buffer)
{
// Missing streamed client data
UNIMPLEMENTED();
continue;
}
if (buffer->getMappedState())
Expand All @@ -1177,4 +1227,24 @@ angle::Result ContextWgpu::handleDirtyVertexBuffers(const gl::AttributesMask &sl
return angle::Result::Continue;
}

angle::Result ContextWgpu::handleDirtyIndexBuffer(gl::DrawElementsType indexType,
DirtyBits::Iterator *dirtyBitsIterator)
{
VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
webgpu::BufferHelper *buffer = vertexArrayWgpu->getIndexBuffer();
if (!buffer)
{
// Missing streamed client data
UNIMPLEMENTED();
return angle::Result::Continue;
}
if (buffer->getMappedState())
{
ANGLE_TRY(buffer->unmap());
}
mCommandBuffer.setIndexBuffer(buffer->getBuffer(), gl_wgpu::GetIndexFormat(indexType), 0, -1);
mCurrentIndexBufferType = indexType;
return angle::Result::Continue;
}

} // namespace rx
15 changes: 8 additions & 7 deletions src/libANGLE/renderer/wgpu/ContextWgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ class ContextWgpu : public ContextImpl

void invalidateVertexBuffer(size_t slot);
void invalidateVertexBuffers();
void invalidateIndexBuffer();

private:
// Dirty bits.
Expand All @@ -301,6 +302,7 @@ class ContextWgpu : public ContextImpl
DIRTY_BIT_SCISSOR,

DIRTY_BIT_VERTEX_BUFFERS,
DIRTY_BIT_INDEX_BUFFER,

DIRTY_BIT_MAX,
};
Expand All @@ -325,26 +327,23 @@ class ContextWgpu : public ContextImpl
mDirtyBits.set(DIRTY_BIT_RENDER_PIPELINE_DESC);
}

angle::Result setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei indexCount,
GLsizei instanceCount,
gl::DrawElementsType indexType,
const void *indices);
angle::Result setupDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLint firstVertexOrInvalid,
GLsizei vertexOrIndexCount,
GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices);
const void *indices,
uint32_t *outFirstIndex);

angle::Result handleDirtyRenderPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyRenderPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyViewport(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyScissor(DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyVertexBuffers(const gl::AttributesMask &slots,
DirtyBits::Iterator *dirtyBitsIterator);
angle::Result handleDirtyIndexBuffer(gl::DrawElementsType indexType,
DirtyBits::Iterator *dirtyBitsIterator);

angle::Result handleDirtyRenderPass(DirtyBits::Iterator *dirtyBitsIterator);

Expand All @@ -360,6 +359,8 @@ class ContextWgpu : public ContextImpl
webgpu::RenderPipelineDesc mRenderPipelineDesc;
wgpu::RenderPipeline mCurrentGraphicsPipeline;
gl::AttributesMask mCurrentRenderPipelineAllAttributes;

gl::DrawElementsType mCurrentIndexBufferType = gl::DrawElementsType::InvalidEnum;
};

} // namespace rx
Expand Down
45 changes: 45 additions & 0 deletions src/libANGLE/renderer/wgpu/VertexArrayWgpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ angle::Result VertexArrayWgpu::syncState(const gl::Context *context,
break;

case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
ANGLE_TRY(syncDirtyElementArrayBuffer(contextWgpu));
contextWgpu->invalidateIndexBuffer();
break;

case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
Expand Down Expand Up @@ -86,6 +88,33 @@ angle::Result VertexArrayWgpu::syncState(const gl::Context *context,
return angle::Result::Continue;
}

angle::Result VertexArrayWgpu::syncClientArrays(const gl::Context *context,
const gl::AttributesMask &activeAttributesMask,
GLint first,
GLsizei count,
gl::DrawElementsType drawElementsTypeOrInvalid,
const void *indices,
GLsizei instanceCount,
bool primitiveRestartEnabled,
const void **adjustedIndicesPtr)
{
gl::AttributesMask clientAttributesToSync =
mState.getClientMemoryAttribsMask() & activeAttributesMask;
if (clientAttributesToSync.any())
{
UNIMPLEMENTED();
}

if (drawElementsTypeOrInvalid != gl::DrawElementsType::InvalidEnum &&
!mState.getElementArrayBuffer())
{
UNIMPLEMENTED();
}

*adjustedIndicesPtr = indices;
return angle::Result::Continue;
}

angle::Result VertexArrayWgpu::syncDirtyAttrib(ContextWgpu *contextWgpu,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
Expand Down Expand Up @@ -123,4 +152,20 @@ angle::Result VertexArrayWgpu::syncDirtyAttrib(ContextWgpu *contextWgpu,
return angle::Result::Continue;
}

angle::Result VertexArrayWgpu::syncDirtyElementArrayBuffer(ContextWgpu *contextWgpu)
{
gl::Buffer *bufferGl = mState.getElementArrayBuffer();
if (bufferGl)
{
BufferWgpu *buffer = webgpu::GetImpl(bufferGl);
mCurrentIndexBuffer = &buffer->getBuffer();
}
else
{
mCurrentIndexBuffer = nullptr;
}

return angle::Result::Continue;
}

} // namespace rx
13 changes: 13 additions & 0 deletions src/libANGLE/renderer/wgpu/VertexArrayWgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,28 @@ class VertexArrayWgpu : public VertexArrayImpl
gl::VertexArray::DirtyBindingBitsArray *bindingBits) override;

webgpu::BufferHelper *getVertexBuffer(size_t slot) const { return mCurrentArrayBuffers[slot]; }
webgpu::BufferHelper *getIndexBuffer() const { return mCurrentIndexBuffer; }

angle::Result syncClientArrays(const gl::Context *context,
const gl::AttributesMask &activeAttributesMask,
GLint first,
GLsizei count,
gl::DrawElementsType drawElementsTypeOrInvalid,
const void *indices,
GLsizei instanceCount,
bool primitiveRestartEnabled,
const void **adjustedIndicesPtr);

private:
angle::Result syncDirtyAttrib(ContextWgpu *contextWgpu,
const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
size_t attribIndex);
angle::Result syncDirtyElementArrayBuffer(ContextWgpu *contextWgpu);

gl::AttribArray<webgpu::PackedVertexAttribute> mCurrentAttribs;
gl::AttribArray<webgpu::BufferHelper *> mCurrentArrayBuffers;
webgpu::BufferHelper *mCurrentIndexBuffer = nullptr;
};

} // namespace rx
Expand Down
Loading

0 comments on commit 0b61071

Please sign in to comment.