Bug 1879178 - Add UninitializedBufferData_SizeOnly for unitialized orphaning of WebGL buffers. r=jgilbert

Currently BufferData when supplied null data, a pattern explicitly recommended in OpenGL for orphaning
buffer before they are subsequently filled with BufferSubData, currently causes zero data to be calloc'd
and uploaded to the buffer, which can be expensive.

In trusted code that only directly accesses WebGLContext, we can add an UninitializedBufferData_SizeOnly
call that can be used for this initialization, with the understanding that subsequent BufferSubData calls
will fill in relevant sections of the buffer before they are ever used.

Differential Revision: https://phabricator.services.mozilla.com/D201176
This commit is contained in:
Lee Salzman 2024-02-08 23:36:56 +00:00
parent 96f3f29b27
commit 2590ec2804
5 changed files with 22 additions and 6 deletions

View File

@ -1256,9 +1256,9 @@ static const float kRectVertexData[12] = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
// buffers.
void SharedContextWebgl::ResetPathVertexBuffer(bool aChanged) {
mWebgl->BindBuffer(LOCAL_GL_ARRAY_BUFFER, mPathVertexBuffer.get());
mWebgl->BufferData(
mWebgl->UninitializedBufferData_SizeOnly(
LOCAL_GL_ARRAY_BUFFER,
std::max(size_t(mPathVertexCapacity), sizeof(kRectVertexData)), nullptr,
std::max(size_t(mPathVertexCapacity), sizeof(kRectVertexData)),
LOCAL_GL_DYNAMIC_DRAW);
mWebgl->BufferSubData(LOCAL_GL_ARRAY_BUFFER, 0, sizeof(kRectVertexData),
(const uint8_t*)kRectVertexData);

View File

@ -75,7 +75,8 @@ static bool ValidateBufferUsageEnum(WebGLContext* webgl, GLenum usage) {
}
void WebGLBuffer::BufferData(const GLenum target, const uint64_t size,
const void* const maybeData, const GLenum usage) {
const void* const maybeData, const GLenum usage,
bool allowUninitialized) {
// The driver knows only GLsizeiptr, which is int32_t on 32bit!
bool sizeValid = CheckedInt<GLsizeiptr>(size).isValid();
@ -104,7 +105,7 @@ void WebGLBuffer::BufferData(const GLenum target, const uint64_t size,
const void* uploadData = maybeData;
UniqueBuffer maybeCalloc;
if (!uploadData) {
if (!uploadData && !allowUninitialized) {
maybeCalloc = UniqueBuffer::Take(calloc(1, AssertedCast<size_t>(size)));
if (!maybeCalloc) {
mContext->ErrorOutOfMemory("Failed to alloc zeros.");
@ -112,7 +113,7 @@ void WebGLBuffer::BufferData(const GLenum target, const uint64_t size,
}
uploadData = maybeCalloc.get();
}
MOZ_ASSERT(uploadData);
MOZ_ASSERT(uploadData || allowUninitialized);
UniqueBuffer newIndexCache;
const bool needsIndexCache = mContext->mNeedsIndexValidation ||

View File

@ -41,7 +41,8 @@ class WebGLBuffer final : public WebGLContextBoundObject {
bool ValidateRange(size_t byteOffset, size_t byteLen) const;
bool ValidateCanBindToTarget(GLenum target);
void BufferData(GLenum target, uint64_t size, const void* data, GLenum usage);
void BufferData(GLenum target, uint64_t size, const void* data, GLenum usage,
bool allowUninitialized = false);
void BufferSubData(GLenum target, uint64_t dstByteOffset, uint64_t dataLen,
const void* data, bool unsynchronized = false) const;

View File

@ -685,6 +685,8 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
void BufferData(GLenum target, uint64_t dataLen, const uint8_t* data,
GLenum usage) const;
void UninitializedBufferData_SizeOnly(GLenum target, uint64_t dataLen,
GLenum usage) const;
// The unsynchronized flag may allow for better performance when
// interleaving buffer updates with draw calls. However, care must
// be taken. This has similar semantics to glMapBufferRange's

View File

@ -251,6 +251,18 @@ void WebGLContext::BufferData(GLenum target, uint64_t dataLen,
buffer->BufferData(target, dataLen, data, usage);
}
void WebGLContext::UninitializedBufferData_SizeOnly(GLenum target,
uint64_t dataLen,
GLenum usage) const {
const FuncScope funcScope(*this, "bufferData");
if (IsContextLost()) return;
const auto& buffer = ValidateBufferSelection(target);
if (!buffer) return;
buffer->BufferData(target, dataLen, nullptr, usage, true);
}
////////////////////////////////////////
void WebGLContext::BufferSubData(GLenum target, uint64_t dstByteOffset,