Add debug checks to enforce gpu buffer access patterns.

Specifically make sure it is true that we only write to static and stream
access buffers once.

Bug: skia:11226
Change-Id: I566a095093e884075bc4bee07ba1101e772e3332
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/360476
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2021-01-27 10:21:21 -05:00 committed by Skia Commit-Bot
parent 1e1fe122f5
commit c1ea3d9b8e
6 changed files with 32 additions and 10 deletions

View File

@ -21,6 +21,7 @@ void* GrGpuBuffer::map() {
if (this->wasDestroyed()) {
return nullptr;
}
SkASSERT(!fHasWrittenToBuffer || fAccessPattern == kDynamic_GrAccessPattern);
if (!fMapPtr) {
this->onMap();
}
@ -34,17 +35,27 @@ void GrGpuBuffer::unmap() {
SkASSERT(fMapPtr);
this->onUnmap();
fMapPtr = nullptr;
#ifdef SK_DEBUG
fHasWrittenToBuffer = true;
#endif
}
bool GrGpuBuffer::isMapped() const { return SkToBool(fMapPtr); }
bool GrGpuBuffer::updateData(const void* src, size_t srcSizeInBytes) {
SkASSERT(!fHasWrittenToBuffer || fAccessPattern == kDynamic_GrAccessPattern);
SkASSERT(!this->isMapped());
SkASSERT(srcSizeInBytes <= fSizeInBytes);
if (this->intendedType() == GrGpuBufferType::kXferGpuToCpu) {
return false;
}
return this->onUpdateData(src, srcSizeInBytes);
bool result = this->onUpdateData(src, srcSizeInBytes);
#ifdef SK_DEBUG
if (result) {
fHasWrittenToBuffer = true;
}
#endif
return result;
}
void GrGpuBuffer::ComputeScratchKeyForDynamicVBO(size_t size, GrGpuBufferType intendedType,

View File

@ -98,6 +98,12 @@ private:
size_t fSizeInBytes;
GrAccessPattern fAccessPattern;
GrGpuBufferType fIntendedType;
#ifdef SK_DEBUG
// Static and stream access buffers are only ever written to once. This is used to track that
// and assert it is true.
bool fHasWrittenToBuffer = false;
#endif
};
#endif

View File

@ -197,7 +197,8 @@ void GrVkBuffer::copyCpuDataToGpuBuffer(GrVkGpu* gpu, const void* src, size_t si
gpu->updateBuffer(this, src, this->offset(), size);
} else {
sk_sp<GrVkTransferBuffer> transferBuffer =
GrVkTransferBuffer::Make(gpu, size, GrVkBuffer::kCopyRead_Type);
GrVkTransferBuffer::Make(gpu, size, GrVkBuffer::kCopyRead_Type,
kStream_GrAccessPattern);
if (!transferBuffer) {
return;
}

View File

@ -423,12 +423,12 @@ sk_sp<GrGpuBuffer> GrVkGpu::onCreateBuffer(size_t size, GrGpuBufferType type,
case GrGpuBufferType::kXferCpuToGpu:
SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
kStream_GrAccessPattern == accessPattern);
buff = GrVkTransferBuffer::Make(this, size, GrVkBuffer::kCopyRead_Type);
buff = GrVkTransferBuffer::Make(this, size, GrVkBuffer::kCopyRead_Type, accessPattern);
break;
case GrGpuBufferType::kXferGpuToCpu:
SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
kStream_GrAccessPattern == accessPattern);
buff = GrVkTransferBuffer::Make(this, size, GrVkBuffer::kCopyWrite_Type);
buff = GrVkTransferBuffer::Make(this, size, GrVkBuffer::kCopyWrite_Type, accessPattern);
break;
default:
SK_ABORT("Unknown buffer type.");

View File

@ -10,7 +10,8 @@
#include "src/gpu/vk/GrVkTransferBuffer.h"
sk_sp<GrVkTransferBuffer> GrVkTransferBuffer::Make(GrVkGpu* gpu, size_t size,
GrVkBuffer::Type type) {
GrVkBuffer::Type type,
GrAccessPattern access) {
GrVkBuffer::Desc desc;
desc.fDynamic = true;
SkASSERT(GrVkBuffer::kCopyRead_Type == type || GrVkBuffer::kCopyWrite_Type == type);
@ -22,19 +23,21 @@ sk_sp<GrVkTransferBuffer> GrVkTransferBuffer::Make(GrVkGpu* gpu, size_t size,
return nullptr;
}
GrVkTransferBuffer* buffer = new GrVkTransferBuffer(gpu, desc, bufferResource);
GrVkTransferBuffer* buffer = new GrVkTransferBuffer(gpu, desc, access, bufferResource);
if (!buffer) {
bufferResource->unref();
}
return sk_sp<GrVkTransferBuffer>(buffer);
}
GrVkTransferBuffer::GrVkTransferBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc,
GrVkTransferBuffer::GrVkTransferBuffer(GrVkGpu* gpu,
const GrVkBuffer::Desc& desc,
GrAccessPattern access,
const GrVkBuffer::Resource* bufferResource)
: INHERITED(gpu, desc.fSizeInBytes,
kCopyRead_Type == desc.fType ? GrGpuBufferType::kXferCpuToGpu
: GrGpuBufferType::kXferGpuToCpu,
kStream_GrAccessPattern)
access)
, GrVkBuffer(desc, bufferResource) {
this->registerWithCache(SkBudgeted::kYes);
}

View File

@ -16,14 +16,15 @@ class GrVkGpu;
class GrVkTransferBuffer : public GrGpuBuffer, public GrVkBuffer {
public:
static sk_sp<GrVkTransferBuffer> Make(GrVkGpu* gpu, size_t size, GrVkBuffer::Type type);
static sk_sp<GrVkTransferBuffer> Make(GrVkGpu* gpu, size_t size, GrVkBuffer::Type type,
GrAccessPattern access);
protected:
void onAbandon() override;
void onRelease() override;
private:
GrVkTransferBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc,
GrVkTransferBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc, GrAccessPattern access,
const GrVkBuffer::Resource* resource);
void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
const SkString& dumpName) const override;