зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 969534e11452 (bug 1843296) for webgpu crash
This commit is contained in:
Родитель
9cf23f6234
Коммит
72983cc276
|
@ -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,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче