[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); std::make_unique<MapRequestTask>(GetDevice()->GetPlatform(), this, mLastMapID);
TRACE_EVENT1(GetDevice()->GetPlatform(), General, "Buffer::APIMapAsync", "serial", TRACE_EVENT1(GetDevice()->GetPlatform(), General, "Buffer::APIMapAsync", "serial",
uint64_t(mLastUsageSerial)); uint64_t(mLastUsageSerial));
if (mLastUsageSerial != kMaxExecutionSerial) { GetDevice()->GetQueue()->TrackTask(std::move(request), mLastUsageSerial);
GetDevice()->GetQueue()->TrackTask(std::move(request), mLastUsageSerial);
} else {
GetDevice()->GetQueue()->TrackTaskAfterEventualFlush(std::move(request));
}
} }
void* BufferBase::APIGetMappedRange(size_t offset, size_t size) { 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) Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) { : BufferBase(device, descriptor) {
// TODO(penghuang): track usage for GL.
mLastUsageSerial = kMaxExecutionSerial;
const OpenGLFunctions& gl = device->GetGL(); const OpenGLFunctions& gl = device->GetGL();
// Allocate at least 4 bytes so clamped accesses are always in bounds. // Allocate at least 4 bytes so clamped accesses are always in bounds.
mAllocatedSize = std::max(GetSize(), uint64_t(4u)); 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); std::vector<uint8_t> clearValues(mAllocatedSize, 1u);
gl.BufferData(GL_ARRAY_BUFFER, mAllocatedSize, clearValues.data(), GL_STATIC_DRAW); gl.BufferData(GL_ARRAY_BUFFER, mAllocatedSize, clearValues.data(), GL_STATIC_DRAW);
} else { } 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); gl.BufferData(GL_ARRAY_BUFFER, mAllocatedSize, nullptr, GL_STATIC_DRAW);
} }
TrackUsage();
} }
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor, bool shouldLazyClear) 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()); gl.BufferSubData(GL_ARRAY_BUFFER, 0, size, clearValues.data());
device->IncrementLazyClearCountForTesting(); device->IncrementLazyClearCountForTesting();
TrackUsage();
SetIsDataInitialized(); 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); mappedData = gl.MapBufferRange(GL_ARRAY_BUFFER, offset, size, GL_MAP_READ_BIT);
} else { } else {
ASSERT(mode & wgpu::MapMode::Write); 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 // 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(uint64_t offset, uint64_t size);
bool EnsureDataInitializedAsDestination(const CopyTextureToBufferCmd* copy); bool EnsureDataInitializedAsDestination(const CopyTextureToBufferCmd* copy);
void TrackUsage() { MarkUsedInPendingCommands(); }
private: private:
Buffer(Device* device, const BufferDescriptor* descriptor, bool shouldLazyClear); Buffer(Device* device, const BufferDescriptor* descriptor, bool shouldLazyClear);
~Buffer() override; ~Buffer() override;

View File

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

View File

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

View File

@ -140,6 +140,8 @@ class Device final : public DeviceBase {
GLFormatTable mFormatTable; GLFormatTable mFormatTable;
std::unique_ptr<Context> mContext = nullptr; 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 } // namespace dawn::native::opengl

View File

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