Compare commits

...

4 Commits

Author SHA1 Message Date
Syed Idris Shah
5d59459f90 Dawn change to enable writeBuffer for size != multiple of 4 2025-05-06 14:07:05 -04:00
bridgewaterrobbie
4249ff6cfb WebGPU: HelloTraingle hacks
Co-authored-by: Andy Hovingh <6198728+AndyHovingh@users.noreply.github.com>
2025-05-06 14:07:05 -04:00
bridgewaterrobbie
1076433fc0 Use variant layout label if available 2025-05-06 14:06:53 -04:00
bridgewaterrobbie
3bd0039ee9 Minimal labels implementation for descriptorset layout 2025-05-06 13:22:33 -04:00
6 changed files with 191 additions and 70 deletions

View File

@@ -39,6 +39,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <utils/StaticString.h>
/** /**
* Types and enums used by filament's driver. * Types and enums used by filament's driver.
@@ -1139,6 +1140,7 @@ struct ExternalSamplerDatum {
static_assert(sizeof(ExternalSamplerDatum) == 12); static_assert(sizeof(ExternalSamplerDatum) == 12);
struct DescriptorSetLayout { struct DescriptorSetLayout {
std::variant<utils::StaticString, utils::CString, std::monostate> label;
utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings; utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings;
// TODO: uncomment when needed // TODO: uncomment when needed

View File

@@ -119,6 +119,44 @@ wgpu::VertexFormat getVertexFormat(filament::backend::ElementType type, bool nor
} }
} }
wgpu::StringView getUserTextureLabel(filament::backend::SamplerType target) {
// TODO will be helpful to get more useful info than this
using filament::backend::SamplerType;
switch (target) {
case SamplerType::SAMPLER_2D:
return "a_2D_user_texture";
case SamplerType::SAMPLER_2D_ARRAY:
return "a_2D_array_user_texture";
case SamplerType::SAMPLER_CUBEMAP:
return "a_cube_map_user_texture";
case SamplerType::SAMPLER_EXTERNAL:
return "an_external_user_texture";
case SamplerType::SAMPLER_3D:
return "a_3D_user_texture";
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return "a_cube_mape_array_user_texture";
}
}
wgpu::StringView getUserTextureViewLabel(filament::backend::SamplerType target) {
// TODO will be helpful to get more useful info than this
using filament::backend::SamplerType;
switch (target) {
case SamplerType::SAMPLER_2D:
return "a_2D_user_texture_view";
case SamplerType::SAMPLER_2D_ARRAY:
return "a_2D_array_user_texture_view";
case SamplerType::SAMPLER_CUBEMAP:
return "a_cube_map_user_texture_view";
case SamplerType::SAMPLER_EXTERNAL:
return "an_external_user_texture_view";
case SamplerType::SAMPLER_3D:
return "a_3D_user_texture_view";
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return "a_cube_mape_array_user_texture_view";
}
}
}// namespace }// namespace
namespace filament::backend { namespace filament::backend {
@@ -201,6 +239,15 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
wgpu::Device const& device) { wgpu::Device const& device) {
assert_invariant(device); assert_invariant(device);
std::string baseLabel;
if (std::holds_alternative<utils::StaticString>(layout.label)) {
const auto& temp = std::get_if<utils::StaticString>(&layout.label);
baseLabel = temp->c_str();
} else if (std::holds_alternative<utils::CString>(layout.label)) {
const auto& temp = std::get_if<utils::CString>(&layout.label);
baseLabel = temp->c_str();
}
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for // TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
// debugging. For now, hack an incrementing value. // debugging. For now, hack an incrementing value.
static int layoutNum = 0; static int layoutNum = 0;
@@ -235,6 +282,14 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
// We are simply hoping that undefined and defaults suffices here. // We are simply hoping that undefined and defaults suffices here.
samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering; // Example default samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering; // Example default
wEntry.texture.sampleType = wgpu::TextureSampleType::Float; // Example default wEntry.texture.sampleType = wgpu::TextureSampleType::Float; // Example default
// TODO: FIX! THIS IS HACK FOR HELLO-TRIANGLE!
if (baseLabel.find("Skybox") != std::string::npos ||
(baseLabel == "Filament Default Material_perView" && wEntry.binding == 22)) {
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
} else {
wEntry.texture.viewDimension =
wgpu::TextureViewDimension::e2D;// Example default
}
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW; entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW;
break; break;
} }
@@ -258,7 +313,7 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
} }
// fEntry.count is unused currently // fEntry.count is unused currently
} }
std::string label = "layout_"+ std::to_string(++layoutNum) ; std::string label = "layout_" + baseLabel + std::to_string(++layoutNum) ;
wgpu::BindGroupLayoutDescriptor layoutDescriptor{ wgpu::BindGroupLayoutDescriptor layoutDescriptor{
.label{label.c_str()}, // Use .c_str() if label needs to be const char* .label{label.c_str()}, // Use .c_str() if label needs to be const char*
.entryCount = wEntries.size(), .entryCount = wEntries.size(),
@@ -450,49 +505,65 @@ size_t WebGPUDescriptorSet::countEntitiesWithDynamicOffsets() const {
// From createTextureR // From createTextureR
WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, WGPUTexture::WGPUTexture(SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage,
wgpu::Device device) noexcept { wgpu::Device const& device) noexcept {
assert_invariant(
// First the texture aspect samples == 1 ||
wgpu::TextureDescriptor desc; samples == 4 &&
"An invalid number of samples were requested, as WGPU requires the sample "
"count to either be 1 (no multisampling) or 4, at least as of April 2025 of "
"the spec. See https://www.w3.org/TR/webgpu/#texture-creation or "
"https://gpuweb.github.io/gpuweb/#multisample-state");
// First, the texture aspect, starting with the defaults/basic configuration
mUsage = fToWGPUTextureUsage(usage);
mFormat = fToWGPUTextureFormat(format);
wgpu::TextureDescriptor textureDescriptor{
.label = getUserTextureLabel(target),
.usage = mUsage,
.dimension = target == SamplerType::SAMPLER_3D ? wgpu::TextureDimension::e3D
: wgpu::TextureDimension::e2D,
.size = { .width = width, .height = height, .depthOrArrayLayers = depth },
.format = mFormat,
.mipLevelCount = levels,
.sampleCount = samples,
// TODO Is this fine? Could do all-the-things, a naive mapping or get something from
// Filament
.viewFormatCount = 0,
.viewFormats = nullptr,
};
// adjust for specific cases
switch (target) { switch (target) {
case SamplerType::SAMPLER_CUBEMAP:
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
case SamplerType::SAMPLER_2D: case SamplerType::SAMPLER_2D:
mArrayLayerCount = 1;
break;
case SamplerType::SAMPLER_2D_ARRAY: case SamplerType::SAMPLER_2D_ARRAY:
// Should be safe to assume external is 2d mArrayLayerCount = textureDescriptor.size.depthOrArrayLayers;
case SamplerType::SAMPLER_EXTERNAL: {
desc.dimension = wgpu::TextureDimension::e2D;
break; break;
} case SamplerType::SAMPLER_CUBEMAP:
case SamplerType::SAMPLER_3D: { textureDescriptor.size.depthOrArrayLayers = 6;
desc.dimension = wgpu::TextureDimension::e3D; mArrayLayerCount = textureDescriptor.size.depthOrArrayLayers;
break;
case SamplerType::SAMPLER_EXTERNAL:
case SamplerType::SAMPLER_3D:
mArrayLayerCount = 1;
break;
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
textureDescriptor.size.depthOrArrayLayers = depth * 6;
mArrayLayerCount = textureDescriptor.size.depthOrArrayLayers;
break; break;
}
} }
desc.size = { .width = width, .height = height, .depthOrArrayLayers = depth }; assert_invariant(textureDescriptor.format != wgpu::TextureFormat::Undefined &&
desc.format = fToWGPUTextureFormat(format); "Could not find appropriate WebGPU format");
assert_invariant(desc.format != wgpu::TextureFormat::Undefined); mTexture = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(mTexture)
// WGPU requires this to be true. Filament should comply << "Failed to create texture for " << textureDescriptor.label;
assert(samples == 1 || samples || 4); // Second, the texture view aspect
mTexView = makeTextureView(0, levels, target);
desc.sampleCount = samples;
desc.usage = fToWGPUTextureUsage(usage);
desc.mipLevelCount = levels;
// TODO Is this fine? Could do all-the-things, a naive mapping or get something from Filament
desc.viewFormats = nullptr;
texture = device.CreateTexture(&desc);
// TODO should a default levelCount be something other than 0? Sample count?
texView = makeTextureView(0, 1);
} }
// From createTextureViewR // From createTextureViewR
WGPUTexture::WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept { WGPUTexture::WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept {
texture = src->texture; mTexture = src->mTexture;
texView = makeTextureView(baseLevel, levelCount); mTexView = makeTextureView(baseLevel, levelCount, target);
} }
wgpu::TextureUsage WGPUTexture::fToWGPUTextureUsage(const TextureUsage& fUsage) { wgpu::TextureUsage WGPUTexture::fToWGPUTextureUsage(const TextureUsage& fUsage) {
@@ -783,26 +854,48 @@ wgpu::TextureFormat WGPUTexture::fToWGPUTextureFormat(const TextureFormat& fUsag
} }
} }
wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount,
const uint8_t& levelCount) { SamplerType target) {
wgpu::TextureViewDescriptor desc; // starting with the defaults/basic configuration
desc.baseMipLevel = baseLevel; wgpu::TextureViewDescriptor textureViewDescriptor{
desc.mipLevelCount = levelCount; .label = getUserTextureViewLabel(target),
.format = mFormat,
// baseArrayLayer is required, making a guess // dimension depends on target and is set below
desc.baseArrayLayer = 0; .baseMipLevel = baseLevel,
// Have not found an analouge to aspect in other drivers, but ALL should be unrestrictive. .mipLevelCount = levelCount,
// TODO Can we make this better? // baseArrayLayer is required, making a guess
desc.aspect = wgpu::TextureAspect::All; .baseArrayLayer = 0,
.arrayLayerCount = mArrayLayerCount,
// The rest of the properties should be fine to leave as default, using the texture params. // Have not found an analog to aspect in other drivers, but ALL should be unrestrictive.
desc.label = "TODO"; // TODO Can we make this better?
.aspect = wgpu::TextureAspect::All,
desc.format = wgpu::TextureFormat::Undefined; .usage = mUsage
desc.dimension = wgpu::TextureViewDimension::Undefined; };
desc.usage = wgpu::TextureUsage::None; // adjust for specific cases
switch (target) {
return texture.CreateView(&desc); case SamplerType::SAMPLER_2D:
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
break;
case SamplerType::SAMPLER_2D_ARRAY:
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
break;
case SamplerType::SAMPLER_CUBEMAP:
textureViewDescriptor.dimension = wgpu::TextureViewDimension::Cube;
break;
case SamplerType::SAMPLER_EXTERNAL:
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
break;
case SamplerType::SAMPLER_3D:
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e3D;
break;
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
textureViewDescriptor.dimension = wgpu::TextureViewDimension::CubeArray;
break;
}
wgpu::TextureView textureView = mTexture.CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(textureView)
<< "Failed to create texture view " << textureViewDescriptor.label;
return textureView;
} }
WGPURenderTarget::Attachment WGPURenderTarget::getDrawColorAttachment(size_t index) { WGPURenderTarget::Attachment WGPURenderTarget::getDrawColorAttachment(size_t index) {

View File

@@ -173,23 +173,27 @@ class WGPUTexture : public HwTexture {
public: public:
WGPUTexture(SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, WGPUTexture(SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage,
wgpu::Device device) noexcept; wgpu::Device const& device) noexcept;
WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept; WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept;
const wgpu::Texture& getTexture() const { return texture; } const wgpu::Texture& getTexture() const { return mTexture; }
const wgpu::TextureView& getTexView() const { return texView; } const wgpu::TextureView& getTexView() const { return mTexView; }
// Public to allow checking for support of a texture format // Public to allow checking for support of a texture format
static wgpu::TextureFormat fToWGPUTextureFormat(const filament::backend::TextureFormat& fUsage); static wgpu::TextureFormat fToWGPUTextureFormat(const filament::backend::TextureFormat& fUsage);
private: private:
wgpu::TextureView makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount); wgpu::TextureView makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount,
SamplerType target);
// CreateTextureR has info for a texture and sampler. Texture Views are needed for binding, // CreateTextureR has info for a texture and sampler. Texture Views are needed for binding,
// along with a sampler Current plan: Inherit the sampler and Texture to always exist (It is a // along with a sampler Current plan: Inherit the sampler and Texture to always exist (It is a
// ref counted pointer) when making views. View is optional // ref counted pointer) when making views. View is optional
wgpu::Texture texture = nullptr; wgpu::Texture mTexture = nullptr;
wgpu::TextureView texView = nullptr; wgpu::TextureUsage mUsage = wgpu::TextureUsage::None;
wgpu::TextureFormat mFormat = wgpu::TextureFormat::Undefined;
uint32_t mArrayLayerCount = 1;
wgpu::TextureView mTexView = nullptr;
wgpu::TextureUsage fToWGPUTextureUsage(const filament::backend::TextureUsage& fUsage); wgpu::TextureUsage fToWGPUTextureUsage(const filament::backend::TextureUsage& fUsage);
}; };

View File

@@ -1140,6 +1140,7 @@ void FMaterial::precacheDepthVariants(FEngine& engine) {
void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* const parser) { void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* const parser) {
UTILS_UNUSED_IN_RELEASE bool success; UTILS_UNUSED_IN_RELEASE bool success;
success = parser->getDescriptorBindings(&mProgramDescriptorBindings); success = parser->getDescriptorBindings(&mProgramDescriptorBindings);
assert_invariant(success); assert_invariant(success);
@@ -1147,6 +1148,22 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
success = parser->getDescriptorSetLayout(&descriptorSetLayout); success = parser->getDescriptorSetLayout(&descriptorSetLayout);
assert_invariant(success); assert_invariant(success);
// Setup Labels for debugging
utils::CString namestr;
utils::StaticString perViewStr = "_perView";
utils::StaticString singleStr = "_single";
parser->getName(&namestr);
utils::CString singleLabel(namestr.c_str(), namestr.length() + singleStr.length());
memccpy(singleLabel.c_str() + namestr.length(), singleStr.c_str(), '\0', singleStr.length());
utils::CString perViewLabel(namestr.c_str(), namestr.length() + perViewStr.length());
memccpy(perViewLabel.c_str() + namestr.length(), perViewStr.c_str(), '\0', perViewStr.length());
descriptorSetLayout[0].label = namestr;
descriptorSetLayout[1].label = perViewLabel;
mDescriptorSetLayout = { mDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(), engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(descriptorSetLayout[0]) }; engine.getDriverApi(), std::move(descriptorSetLayout[0]) };

View File

@@ -33,11 +33,13 @@ namespace filament::descriptor_sets {
using namespace backend; using namespace backend;
static DescriptorSetLayout const postProcessDescriptorSetLayout{{ static DescriptorSetLayout const postProcessDescriptorSetLayout{
utils::StaticString("postProcess"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
}}; }};
static DescriptorSetLayout const depthVariantDescriptorSetLayout{{ static DescriptorSetLayout const depthVariantDescriptorSetLayout{
utils::StaticString("depthVariant"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
}}; }};
@@ -46,14 +48,16 @@ static DescriptorSetLayout const depthVariantDescriptorSetLayout{{
// dedicated SSR vertex shader), which uses perViewDescriptorSetLayout. // dedicated SSR vertex shader), which uses perViewDescriptorSetLayout.
// This means that PerViewBindingPoints::SHADOWS must be in the layout even though it's not used // This means that PerViewBindingPoints::SHADOWS must be in the layout even though it's not used
// by the SSR variant. // by the SSR variant.
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{{ static DescriptorSetLayout const ssrVariantDescriptorSetLayout{
utils::StaticString("ssrVariant"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE }, { DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR }, { DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
}}; }};
static DescriptorSetLayout perViewDescriptorSetLayout = {{ static DescriptorSetLayout perViewDescriptorSetLayout = {
utils::StaticString("perView"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::LIGHTS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::LIGHTS },
@@ -68,7 +72,8 @@ static DescriptorSetLayout perViewDescriptorSetLayout = {{
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG }, { DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
}}; }};
static DescriptorSetLayout perRenderableDescriptorSetLayout = {{ static DescriptorSetLayout perRenderableDescriptorSetLayout = {
utils::StaticString("perRenderable"),{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS }, { DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },

View File

@@ -229,10 +229,10 @@ MaybeError ValidateWriteBuffer(const DeviceBase* device,
uint64_t size) { uint64_t size) {
DAWN_TRY(device->ValidateObject(buffer)); DAWN_TRY(device->ValidateObject(buffer));
DAWN_INVALID_IF(bufferOffset % 4 != 0, "BufferOffset (%u) is not a multiple of 4.", // DAWN_INVALID_IF(bufferOffset % 4 != 0, "BufferOffset (%u) is not a multiple of 4.",
bufferOffset); // bufferOffset);
//
DAWN_INVALID_IF(size % 4 != 0, "Size (%u) is not a multiple of 4.", size); // DAWN_INVALID_IF(size % 4 != 0, "Size (%u) is not a multiple of 4.", size);
uint64_t bufferSize = buffer->GetSize(); uint64_t bufferSize = buffer->GetSize();
DAWN_INVALID_IF(bufferOffset > bufferSize || size > (bufferSize - bufferOffset), DAWN_INVALID_IF(bufferOffset > bufferSize || size > (bufferSize - bufferOffset),