Skip to content

Commit

Permalink
Volatile dynamic buffers in Metal
Browse files Browse the repository at this point in the history
  • Loading branch information
colincornaby committed Dec 3, 2023
1 parent cb0002a commit 35a886b
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 6 deletions.
1 change: 1 addition & 0 deletions Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class plMetalDevice
// Currently requires a CA drawable and not a Metal drawable. In since CA drawable is only abstract implementation I know about, not sure where we would find others?
void CreateNewCommandBuffer(CA::MetalDrawable* drawable);
MTL::CommandBuffer* GetCurrentCommandBuffer();
MTL::CommandBuffer* GetCurrentDrawableCommandBuffer() { return fCurrentCommandBuffer; }
CA::MetalDrawable* GetCurrentDrawable() const;
/// Submit the command buffer to the GPU and draws all the render passes. Clears the current command buffer.
void SubmitCommandBuffer();
Expand Down
15 changes: 9 additions & 6 deletions Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1953,12 +1953,8 @@ bool plMetalPipeline::ICheckDynBuffers(plDrawableSpans* drawable, plGBufferGroup

// If our vertex buffer ref is volatile and the timestamp is off
// then it needs to be refilled
// MTL::PurgeableState bufferState = vRef->fVertexBuffer->setPurgeableState(MTL::PurgeableStateNonVolatile);
if (vRef->Expired(fVtxRefTime)) {
IRefreshDynVertices(group, vRef);
// fDevice.GetCurrentCommandBuffer()->addCompletedHandler( ^(MTL::CommandBuffer *buffer) {
// vRef->fVertexBuffer->setPurgeableState(MTL::PurgeableStateVolatile);
// });
}

if (iRef->IsDirty()) {
Expand Down Expand Up @@ -1990,12 +1986,19 @@ bool plMetalPipeline::IRefreshDynVertices(plGBufferGroup* group, plMetalVertexBu
vRef->PrepareForWrite();

MTL::Buffer* vertexBuffer = vRef->GetBuffer();
// Metal note: we don't need to check if the buffer is purged, Plasma always wants to refill.
// This works a bit differently than a typical volatile resource pattern where we'd want
// to check if the resource is empty before refilling.
vertexBuffer->setPurgeableState(MTL::PurgeableStateNonVolatile);
if (!vertexBuffer || vertexBuffer->length() < size) {
// Plasma will present different length buffers at different times
vertexBuffer = fDevice.fMetalDevice->newBuffer(vData, size, MTL::ResourceStorageModeManaged)->autorelease();
if (vRef->Volatile()) {
fDevice.GetCurrentCommandBuffer()->addCompletedHandler(^(MTL::CommandBuffer* buffer){
// vRef->fVertexBuffer->setPurgeableState(MTL::PurgeableStateVolatile);
// We need to manually mark the buffer as eligible for freeing after render
// Only allow this resource to be volatile after the on screen command buffer.
// It should not be freed after something like a shadow render command buffer.
fDevice.GetCurrentDrawableCommandBuffer()->addCompletedHandler(^(MTL::CommandBuffer* buffer) {
vertexBuffer->setPurgeableState(MTL::PurgeableStateVolatile);
});
}
vRef->SetBuffer(vertexBuffer);
Expand Down

0 comments on commit 35a886b

Please sign in to comment.