[GL] track buffer usage

With this CL, GL backend and other backends will use the similar way
to track buffer usage, so the GL MapAsync(Write) will not synchronize
GL commands anymore.

Change-Id: I9f8dfeb58faaed09ed62550371a30a680cd607d5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118140
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Peng Huang 2023-02-06 23:29:11 +00:00 committed by Dawn LUCI CQ
parent fc2083a616
commit fd1e8a44f2
7 changed files with 37 additions and 12 deletions

View File

@ -456,11 +456,7 @@ void BufferBase::APIMapAsync(wgpu::MapMode mode,
std::make_unique<MapRequestTask>(GetDevice()->GetPlatform(), this, mLastMapID);
TRACE_EVENT1(GetDevice()->GetPlatform(), General, "Buffer::APIMapAsync", "serial",
uint64_t(mLastUsageSerial));
if (mLastUsageSerial != kMaxExecutionSerial) {
GetDevice()->GetQueue()->TrackTask(std::move(request), mLastUsageSerial);
} else {
GetDevice()->GetQueue()->TrackTaskAfterEventualFlush(std::move(request));
}
}
void* BufferBase::APIGetMappedRange(size_t offset, size_t size) {

View File

@ -39,8 +39,6 @@ ResultOrError<Ref<Buffer>> Buffer::CreateInternalBuffer(Device* device,
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) {
// TODO(penghuang): track usage for GL.
mLastUsageSerial = kMaxExecutionSerial;
const OpenGLFunctions& gl = device->GetGL();
// Allocate at least 4 bytes so clamped accesses are always in bounds.
mAllocatedSize = std::max(GetSize(), uint64_t(4u));
@ -55,9 +53,10 @@ Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
std::vector<uint8_t> clearValues(mAllocatedSize, 1u);
gl.BufferData(GL_ARRAY_BUFFER, mAllocatedSize, clearValues.data(), GL_STATIC_DRAW);
} else {
// Buffers start zeroed if you pass nullptr to glBufferData.
// Buffers start uninitialized if you pass nullptr to glBufferData.
gl.BufferData(GL_ARRAY_BUFFER, mAllocatedSize, nullptr, GL_STATIC_DRAW);
}
TrackUsage();
}
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor, bool shouldLazyClear)
@ -122,6 +121,7 @@ void Buffer::InitializeToZero() {
gl.BufferSubData(GL_ARRAY_BUFFER, 0, size, clearValues.data());
device->IncrementLazyClearCountForTesting();
TrackUsage();
SetIsDataInitialized();
}
@ -160,7 +160,8 @@ MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size)
mappedData = gl.MapBufferRange(GL_ARRAY_BUFFER, offset, size, GL_MAP_READ_BIT);
} else {
ASSERT(mode & wgpu::MapMode::Write);
mappedData = gl.MapBufferRange(GL_ARRAY_BUFFER, offset, size, GL_MAP_WRITE_BIT);
mappedData = gl.MapBufferRange(GL_ARRAY_BUFFER, offset, size,
GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
}
// The frontend asks that the pointer returned by GetMappedPointer is from the start of

View File

@ -37,6 +37,8 @@ class Buffer final : public BufferBase {
bool EnsureDataInitializedAsDestination(uint64_t offset, uint64_t size);
bool EnsureDataInitializedAsDestination(const CopyTextureToBufferCmd* copy);
void TrackUsage() { MarkUsedInPendingCommands(); }
private:
Buffer(Device* device, const BufferDescriptor* descriptor, bool shouldLazyClear);
~Buffer() override;

View File

@ -520,6 +520,9 @@ MaybeError CommandBuffer::Execute() {
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
ToBackend(copy->source)->TrackUsage();
ToBackend(copy->destination)->TrackUsage();
break;
}
@ -560,6 +563,8 @@ MaybeError CommandBuffer::Execute() {
copy->copySize);
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
ToBackend(dst.texture)->Touch();
buffer->TrackUsage();
break;
}
@ -666,6 +671,8 @@ MaybeError CommandBuffer::Execute() {
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
gl.DeleteFramebuffers(1, &readFBO);
buffer->TrackUsage();
break;
}
@ -720,6 +727,7 @@ MaybeError CommandBuffer::Execute() {
gl.BufferSubData(GL_ARRAY_BUFFER, cmd->offset, cmd->size, clearValues.data());
}
dstBuffer->TrackUsage();
break;
}
@ -756,6 +764,8 @@ MaybeError CommandBuffer::Execute() {
gl.BindBuffer(GL_ARRAY_BUFFER, dstBuffer->GetHandle());
gl.BufferSubData(GL_ARRAY_BUFFER, offset, size, data);
dstBuffer->TrackUsage();
break;
}
@ -799,6 +809,8 @@ MaybeError CommandBuffer::ExecuteComputePass() {
gl.BindBuffer(GL_DISPATCH_INDIRECT_BUFFER, indirectBuffer->GetHandle());
gl.DispatchComputeIndirect(static_cast<GLintptr>(indirectBufferOffset));
gl.MemoryBarrier(GL_ALL_BARRIER_BITS);
indirectBuffer->TrackUsage();
break;
}
@ -1056,6 +1068,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
gl.DrawArraysIndirect(
lastPipeline->GetGLPrimitiveTopology(),
reinterpret_cast<void*>(static_cast<intptr_t>(indirectBufferOffset)));
indirectBuffer->TrackUsage();
break;
}
@ -1072,6 +1085,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
gl.DrawElementsIndirect(
lastPipeline->GetGLPrimitiveTopology(), indexBufferFormat,
reinterpret_cast<void*>(static_cast<intptr_t>(draw->indirectOffset)));
indirectBuffer->TrackUsage();
break;
}
@ -1112,6 +1126,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
indexBufferFormat = IndexFormatType(cmd->format);
indexFormatSize = IndexFormatSize(cmd->format);
vertexStateBufferBindingTracker.OnSetIndexBuffer(cmd->buffer.Get());
ToBackend(cmd->buffer)->TrackUsage();
break;
}
@ -1119,6 +1134,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
vertexStateBufferBindingTracker.OnSetVertexBuffer(cmd->slot, cmd->buffer.Get(),
cmd->offset);
ToBackend(cmd->buffer)->TrackUsage();
break;
}

View File

@ -315,10 +315,17 @@ ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
}
void Device::SubmitFenceSync() {
if (!mHasPendingCommands) {
return;
}
const OpenGLFunctions& gl = GetGL();
GLsync sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
IncrementLastSubmittedCommandSerial();
mFencesInFlight.emplace(sync, GetLastSubmittedCommandSerial());
// Reset mHasPendingCommands after GetGL() which will set mHasPendingCommands to true.
mHasPendingCommands = false;
}
MaybeError Device::ValidateEGLImageCanBeWrapped(const TextureDescriptor* descriptor,
@ -381,6 +388,7 @@ TextureBase* Device::CreateTextureWrappingEGLImage(const ExternalImageDescriptor
}
MaybeError Device::TickImpl() {
SubmitFenceSync();
return {};
}
@ -442,9 +450,7 @@ MaybeError Device::WaitForIdleForDestruction() {
}
bool Device::HasPendingCommands() const {
// Technically we could have scheduled commands inside the GL driver that are waiting for a
// glFlush but we can't know for sure so we might as well pretend there are no commands.
return false;
return mHasPendingCommands;
}
uint32_t Device::GetOptimalBytesPerRowAlignment() const {
@ -465,6 +471,7 @@ const OpenGLFunctions& Device::GetGL() const {
if (mContext) {
mContext->MakeCurrent();
}
mHasPendingCommands = true;
return mGL;
}

View File

@ -140,6 +140,8 @@ class Device final : public DeviceBase {
GLFormatTable mFormatTable;
std::unique_ptr<Context> mContext = nullptr;
// Has pending GL commands which are not associated with a fence.
mutable bool mHasPendingCommands = false;
};
} // namespace dawn::native::opengl

View File

@ -48,6 +48,7 @@ MaybeError Queue::WriteBufferImpl(BufferBase* buffer,
gl.BindBuffer(GL_ARRAY_BUFFER, ToBackend(buffer)->GetHandle());
gl.BufferSubData(GL_ARRAY_BUFFER, bufferOffset, size, data);
buffer->MarkUsedInPendingCommands();
return {};
}