Backed out changeset 969534e11452 (bug 1843296) for webgpu crash

This commit is contained in:
Narcis Beleuzu 2023-08-08 01:14:00 +03:00
Родитель 9cf23f6234
Коммит 72983cc276
3 изменённых файлов: 28 добавлений и 59 удалений

Просмотреть файл

@ -16,7 +16,6 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "Device.h" #include "Device.h"
#include "mozilla/webgpu/ffi/wgpu.h"
namespace mozilla::webgpu { namespace mozilla::webgpu {
@ -71,20 +70,22 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE | bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
dom::GPUBufferUsage_Binding::MAP_READ); dom::GPUBufferUsage_Binding::MAP_READ);
bool allocSucceeded = false;
if (hasMapFlags || aDesc.mMappedAtCreation) { if (hasMapFlags || aDesc.mMappedAtCreation) {
// If shmem allocation fails, we continue and provide the parent side with
// an empty shmem which it will interpret as an OOM situtation.
const auto checked = CheckedInt<size_t>(aDesc.mSize); const auto checked = CheckedInt<size_t>(aDesc.mSize);
const size_t maxSize = WGPUMAX_BUFFER_SIZE; if (!checked.isValid()) {
if (checked.isValid() && checked.value() > 0 && checked.value() < maxSize) { aRv.ThrowRangeError("Mappable size is too large");
return nullptr;
}
size_t size = checked.value(); size_t size = checked.value();
auto maybeShmem = ipc::UnsafeSharedMemoryHandle::CreateAndMap(size); auto maybeShmem = ipc::UnsafeSharedMemoryHandle::CreateAndMap(size);
if (maybeShmem.isSome()) { if (maybeShmem.isNothing()) {
allocSucceeded = true; aRv.ThrowRangeError(
nsPrintfCString("Unable to allocate shmem of size %" PRIuPTR, size));
return nullptr;
}
handle = std::move(maybeShmem.ref().first); handle = std::move(maybeShmem.ref().first);
mapping = std::move(maybeShmem.ref().second); mapping = std::move(maybeShmem.ref().second);
@ -93,30 +94,11 @@ already_AddRefed<Buffer> Buffer::Create(Device* aDevice, RawId aDeviceId,
// zero out memory // zero out memory
memset(mapping.Bytes().data(), 0, size); memset(mapping.Bytes().data(), 0, size);
} }
}
if (checked.value() == 0) {
// Zero-sized buffers is a special case. We don't create a shmem since
// allocating the memory would not make sense, however mappable null
// buffers are allowed by the spec so we just pass the null handle which
// in practice deserializes into a null handle on the parent side and
// behaves like a zero-sized allocation.
allocSucceeded = true;
}
}
// If mapped at creation and the shmem allocation failed, immediately throw
// a range error and don't attempt to create the buffer.
if (aDesc.mMappedAtCreation && !allocSucceeded) {
aRv.ThrowRangeError("Allocation failed");
return nullptr;
}
RawId id = actor->DeviceCreateBuffer(aDeviceId, aDesc, std::move(handle)); RawId id = actor->DeviceCreateBuffer(aDeviceId, aDesc, std::move(handle));
RefPtr<Buffer> buffer = RefPtr<Buffer> buffer =
new Buffer(aDevice, id, aDesc.mSize, aDesc.mUsage, std::move(mapping)); new Buffer(aDevice, id, aDesc.mSize, aDesc.mUsage, std::move(mapping));
if (aDesc.mMappedAtCreation) { if (aDesc.mMappedAtCreation) {
// Mapped at creation's raison d'être is write access, since the buffer is // Mapped at creation's raison d'être is write access, since the buffer is
// being created and there isn't anything interesting to read in it yet. // being created and there isn't anything interesting to read in it yet.

Просмотреть файл

@ -385,31 +385,22 @@ ipc::IPCResult WebGPUParent::RecvCreateBuffer(
bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE | bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
dom::GPUBufferUsage_Binding::MAP_READ); dom::GPUBufferUsage_Binding::MAP_READ);
bool shmAllocationFailed = false;
if (hasMapFlags || aDesc.mMappedAtCreation) { if (hasMapFlags || aDesc.mMappedAtCreation) {
if (shmem.Size() < aDesc.mSize) {
MOZ_RELEASE_ASSERT(shmem.Size() == 0);
// If we requested a non-zero mappable buffer and get a size of zero, it
// indicates that the shmem allocation failed on the client side.
shmAllocationFailed = true;
} else {
uint64_t offset = 0; uint64_t offset = 0;
uint64_t size = 0; uint64_t size = 0;
if (aDesc.mMappedAtCreation) { if (aDesc.mMappedAtCreation) {
size = aDesc.mSize; size = aDesc.mSize;
MOZ_RELEASE_ASSERT(shmem.Size() >= aDesc.mSize);
} }
BufferMapData data = {std::move(shmem), hasMapFlags, offset, size}; BufferMapData data = {std::move(shmem), hasMapFlags, offset, size};
mSharedMemoryMap.insert({aBufferId, std::move(data)}); mSharedMemoryMap.insert({aBufferId, std::move(data)});
} }
}
ErrorBuffer error; ErrorBuffer error;
ffi::wgpu_server_device_create_buffer(mContext.get(), aDeviceId, aBufferId, ffi::wgpu_server_device_create_buffer(mContext.get(), aDeviceId, aBufferId,
label.Get(), aDesc.mSize, aDesc.mUsage, label.Get(), aDesc.mSize, aDesc.mUsage,
aDesc.mMappedAtCreation, aDesc.mMappedAtCreation, error.ToFFI());
shmAllocationFailed, error.ToFFI());
ForwardError(aDeviceId, error); ForwardError(aDeviceId, error);
return IPC_OK(); return IPC_OK();
} }
@ -944,7 +935,7 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent(
ErrorBuffer error; ErrorBuffer error;
ffi::wgpu_server_device_create_buffer(mContext.get(), data->mDeviceId, ffi::wgpu_server_device_create_buffer(mContext.get(), data->mDeviceId,
bufferId, nullptr, bufferSize, bufferId, nullptr, bufferSize,
usage, false, false, error.ToFFI()); usage, false, error.ToFFI());
if (ForwardError(data->mDeviceId, error)) { if (ForwardError(data->mDeviceId, error)) {
return IPC_OK(); return IPC_OK();
} }

Просмотреть файл

@ -18,15 +18,12 @@ use std::borrow::Cow;
use std::slice; use std::slice;
use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::atomic::{AtomicU32, Ordering};
// The seemingly redundant u64 suffixes help cbindgen with generating the right C++ code.
// See https://github.com/mozilla/cbindgen/issues/849.
/// We limit the size of buffer allocations for stability reason. /// We limit the size of buffer allocations for stability reason.
/// We can reconsider this limit in the future. Note that some drivers (mesa for example), /// We can reconsider this limit in the future. Note that some drivers (mesa for example),
/// have issues when the size of a buffer, mapping or copy command does not fit into a /// have issues when the size of a buffer, mapping or copy command does not fit into a
/// signed 32 bits integer, so beyond a certain size, large allocations will need some form /// signed 32 bits integer, so beyond a certain size, large allocations will need some form
/// of driver allow/blocklist. /// of driver allow/blocklist.
pub const MAX_BUFFER_SIZE: wgt::BufferAddress = 1u64 << 30u64; const MAX_BUFFER_SIZE: wgt::BufferAddress = 1 << 30;
// Mesa has issues with height/depth that don't fit in a 16 bits signed integers. // Mesa has issues with height/depth that don't fit in a 16 bits signed integers.
const MAX_TEXTURE_EXTENT: u32 = std::i16::MAX as u32; const MAX_TEXTURE_EXTENT: u32 = std::i16::MAX as u32;
@ -282,7 +279,6 @@ pub extern "C" fn wgpu_server_device_create_buffer(
size: wgt::BufferAddress, size: wgt::BufferAddress,
usage: u32, usage: u32,
mapped_at_creation: bool, mapped_at_creation: bool,
shm_allocation_failed: bool,
mut error_buf: ErrorBuffer, mut error_buf: ErrorBuffer,
) { ) {
let utf8_label = label.map(|utf16| utf16.to_string()); let utf8_label = label.map(|utf16| utf16.to_string());
@ -290,7 +286,7 @@ pub extern "C" fn wgpu_server_device_create_buffer(
let usage = wgt::BufferUsages::from_bits_retain(usage); let usage = wgt::BufferUsages::from_bits_retain(usage);
// Don't trust the graphics driver with buffer sizes larger than our conservative max texture size. // Don't trust the graphics driver with buffer sizes larger than our conservative max texture size.
if shm_allocation_failed || size > MAX_BUFFER_SIZE { if size > MAX_BUFFER_SIZE {
error_buf.init(ErrMsg { error_buf.init(ErrMsg {
message: "Out of memory", message: "Out of memory",
r#type: ErrorBufferType::OutOfMemory, r#type: ErrorBufferType::OutOfMemory,