blob: 6d3dd6125eb6e7738e2ef3512adb7cb16362fb56 [file]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tests/Test.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Recording.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/BufferManager.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/RecordingPriv.h"
namespace skgpu::graphite {
namespace {
static bool is_offset_aligned(size_t offset, size_t alignment) {
return 0 == (offset & (alignment - 1));
}
} // namespace
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(BufferManagerGpuOnlyBufferTest, reporter, context,
CtsEnforcement::kApiLevel_202404) {
std::unique_ptr<Recorder> recorder = context->makeRecorder();
DrawBufferManager* mgr = recorder->priv().drawBufferManager();
// Allocate a series of GPU-only buffers. These buffers should not be mapped before and after
// they get transferred to the recording.
auto ssbo = mgr->getStorage(10);
auto vertex = mgr->getVertexStorage(10);
auto index = mgr->getIndexStorage(10);
auto indirect = mgr->getIndirectStorage(10);
REPORTER_ASSERT(reporter, !ssbo.fBuffer->isMapped());
REPORTER_ASSERT(reporter, !vertex.fBuffer->isMapped());
REPORTER_ASSERT(reporter, !index.fBuffer->isMapped());
REPORTER_ASSERT(reporter, !indirect.fBuffer->isMapped());
// Ensure that the buffers' starting alignment matches the required storage buffer alignment.
size_t requiredAlignment = context->priv().caps()->requiredStorageBufferAlignment();
REPORTER_ASSERT(reporter, is_offset_aligned(ssbo.fOffset, requiredAlignment));
REPORTER_ASSERT(reporter, is_offset_aligned(vertex.fOffset, requiredAlignment));
REPORTER_ASSERT(reporter, is_offset_aligned(index.fOffset, requiredAlignment));
REPORTER_ASSERT(reporter, is_offset_aligned(indirect.fOffset, requiredAlignment));
// Transfers the ownership of used buffers to a Recording.
auto recording = recorder->snap();
// Ensure that the buffers are still unmapped.
REPORTER_ASSERT(reporter, !ssbo.fBuffer->isMapped());
REPORTER_ASSERT(reporter, !vertex.fBuffer->isMapped());
REPORTER_ASSERT(reporter, !index.fBuffer->isMapped());
REPORTER_ASSERT(reporter, !indirect.fBuffer->isMapped());
// Since these buffers never need their contents to be host-visible, no buffer transfer/copy
// tasks should have been created for them.
REPORTER_ASSERT(reporter, !recording->priv().hasTasks());
// Request a mapped ssbo followed by an unmapped one. The two buffers should be distinct.
auto [ssboWriter, mappedSsbo, _] = mgr->getMappedStorageBuffer(/*count=*/10, /*stride=*/1);
ssbo = mgr->getStorage(10);
REPORTER_ASSERT(reporter, !ssbo.fBuffer->isMapped());
REPORTER_ASSERT(reporter, ssbo.fBuffer != mappedSsbo.fBuffer);
}
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(BufferManagerStaleAllocatorTest, reporter, context,
CtsEnforcement::kApiLevel_202404) {
std::unique_ptr<Recorder> recorder = context->makeRecorder();
DrawBufferManager* dbm = recorder->priv().drawBufferManager();
// Keep a reference to the buffer to prevent reuse false positives.
sk_sp<const Buffer> rawBuffer;
{
auto [writer, binding, allocator] = dbm->getMappedIndexBuffer(/*count=*/16);
REPORTER_ASSERT(reporter, allocator.isValid());
rawBuffer = sk_ref_sp(binding.fBuffer);
REPORTER_ASSERT(reporter, rawBuffer != nullptr);
// Force the buffer allocator to fail to simulate an allocation failure
dbm->testingOnly_onFailedBuffer();
REPORTER_ASSERT(reporter, dbm->hasMappingFailed());
// BufferSubAllocator::reset() is called on allocator destruction
}
// Recorder::snap() failure branch clears fMappingFailed and drops the failed Recording.
auto failedRecording = recorder->snap();
REPORTER_ASSERT(reporter, !failedRecording);
// Purge everything in the cache by setting the max budget to 0 and freeing all resources
size_t originalBudget = recorder->maxBudgetedBytes();
recorder->setMaxBudgetedBytes(0);
recorder->freeGpuResources();
recorder->setMaxBudgetedBytes(originalBudget); // probably unnecessary but safe
// Get another allocator
auto [staleWriter, staleBinding, staleAllocator] = dbm->getMappedIndexBuffer(/*count=*/16);
REPORTER_ASSERT(reporter, staleAllocator.isValid());
// The buffer should not be the same as rawBuffer
REPORTER_ASSERT(reporter, staleBinding.fBuffer != rawBuffer.get());
auto successRecording = recorder->snap();
REPORTER_ASSERT(reporter, successRecording);
}
} // namespace skgpu::graphite