mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 14:43:31 +00:00
Add missing WebGPU limits to Constants.h
This will help check that the Vulkan devices are enough for WebGPU in a following CL. In addition to additional limits this CL: - Change maxColorAttachments 4 -> 8 to match WebGPU - Renames kMinDynamicBufferOffsetAlignment to kMinUniformBufferOffsetAlignment. - Renames kMaxVertexBufferStride to kMaxVertexBufferArrayStride. - Changes validation of buffer offsets to use the separate uniform and storage limits (but no test is added because they are the same). - Adds validation and a test for kMaxStorageBufferBindingSize. - Augment the null::Device memory limit for that new test (it allocates a buffer of 512MB). - Fix the maxColorAttachment test to not use hardcoded values. Bug: dawn:796 Change-Id: Ibe4219130a44355ae91c02aaa0a41cf5d9f9e234 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/56081 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
895bc934bb
commit
73b7cd624f
@ -37,7 +37,7 @@ float RandomFloat(float min, float max) {
|
|||||||
|
|
||||||
constexpr size_t kNumTriangles = 10000;
|
constexpr size_t kNumTriangles = 10000;
|
||||||
|
|
||||||
struct alignas(kMinDynamicBufferOffsetAlignment) ShaderData {
|
struct alignas(kMinUniformBufferOffsetAlignment) ShaderData {
|
||||||
float scale;
|
float scale;
|
||||||
float time;
|
float time;
|
||||||
float offsetX;
|
float offsetX;
|
||||||
|
@ -20,26 +20,31 @@
|
|||||||
static constexpr uint32_t kMaxBindGroups = 4u;
|
static constexpr uint32_t kMaxBindGroups = 4u;
|
||||||
static constexpr uint8_t kMaxVertexAttributes = 16u;
|
static constexpr uint8_t kMaxVertexAttributes = 16u;
|
||||||
static constexpr uint8_t kMaxVertexBuffers = 8u;
|
static constexpr uint8_t kMaxVertexBuffers = 8u;
|
||||||
static constexpr uint32_t kMaxVertexBufferStride = 2048u;
|
static constexpr uint32_t kMaxVertexBufferArrayStride = 2048u;
|
||||||
static constexpr uint32_t kNumStages = 3;
|
static constexpr uint32_t kNumStages = 3;
|
||||||
static constexpr uint8_t kMaxColorAttachments = 4u;
|
static constexpr uint8_t kMaxColorAttachments = 8u;
|
||||||
static constexpr uint32_t kTextureBytesPerRowAlignment = 256u;
|
static constexpr uint32_t kTextureBytesPerRowAlignment = 256u;
|
||||||
// Dynamic buffer offsets require offset to be divisible by 256
|
static constexpr uint32_t kMaxInterStageShaderComponents = 60u;
|
||||||
static constexpr uint64_t kMinDynamicBufferOffsetAlignment = 256u;
|
static constexpr uint32_t kMaxComputeWorkgroupStorageSize = 16352u;
|
||||||
|
static constexpr uint32_t kMaxComputeWorkgroupInvocations = 256u;
|
||||||
|
static constexpr uint32_t kMaxComputePerDimensionDispatchSize = 65535u;
|
||||||
|
|
||||||
// Per stage limits
|
// Per stage limits
|
||||||
static constexpr uint32_t kMaxSampledTexturesPerShaderStage = 16;
|
static constexpr uint32_t kMaxSampledTexturesPerShaderStage = 16;
|
||||||
static constexpr uint32_t kMaxSamplersPerShaderStage = 16;
|
static constexpr uint32_t kMaxSamplersPerShaderStage = 16;
|
||||||
static constexpr uint32_t kMaxStorageBuffersPerShaderStage = 8;
|
static constexpr uint32_t kMaxStorageBuffersPerShaderStage = 8;
|
||||||
static constexpr uint32_t kMaxStorageTexturesPerShaderStage = 8;
|
static constexpr uint32_t kMaxStorageTexturesPerShaderStage = 4;
|
||||||
static constexpr uint32_t kMaxUniformBuffersPerShaderStage = 12;
|
static constexpr uint32_t kMaxUniformBuffersPerShaderStage = 12;
|
||||||
|
|
||||||
// Per pipeline layout limits
|
// Per pipeline layout limits
|
||||||
static constexpr uint32_t kMaxDynamicUniformBuffersPerPipelineLayout = 8u;
|
static constexpr uint32_t kMaxDynamicUniformBuffersPerPipelineLayout = 8u;
|
||||||
static constexpr uint32_t kMaxDynamicStorageBuffersPerPipelineLayout = 4u;
|
static constexpr uint32_t kMaxDynamicStorageBuffersPerPipelineLayout = 4u;
|
||||||
|
|
||||||
// Max size of uniform buffer binding
|
// Buffer binding constraints
|
||||||
static constexpr uint64_t kMaxUniformBufferBindingSize = 16384u;
|
static constexpr uint64_t kMaxUniformBufferBindingSize = 16384u;
|
||||||
|
static constexpr uint64_t kMaxStorageBufferBindingSize = 134217728u;
|
||||||
|
static constexpr uint64_t kMinUniformBufferOffsetAlignment = 256u;
|
||||||
|
static constexpr uint64_t kMinStorageBufferOffsetAlignment = 256u;
|
||||||
|
|
||||||
// Indirect command sizes
|
// Indirect command sizes
|
||||||
static constexpr uint64_t kDispatchIndirectSize = 3 * sizeof(uint32_t);
|
static constexpr uint64_t kDispatchIndirectSize = 3 * sizeof(uint32_t);
|
||||||
|
@ -44,19 +44,23 @@ namespace dawn_native {
|
|||||||
|
|
||||||
wgpu::BufferUsage requiredUsage;
|
wgpu::BufferUsage requiredUsage;
|
||||||
uint64_t maxBindingSize;
|
uint64_t maxBindingSize;
|
||||||
|
uint64_t requiredBindingAlignment;
|
||||||
switch (bindingInfo.buffer.type) {
|
switch (bindingInfo.buffer.type) {
|
||||||
case wgpu::BufferBindingType::Uniform:
|
case wgpu::BufferBindingType::Uniform:
|
||||||
requiredUsage = wgpu::BufferUsage::Uniform;
|
requiredUsage = wgpu::BufferUsage::Uniform;
|
||||||
maxBindingSize = kMaxUniformBufferBindingSize;
|
maxBindingSize = kMaxUniformBufferBindingSize;
|
||||||
|
requiredBindingAlignment = kMinUniformBufferOffsetAlignment;
|
||||||
break;
|
break;
|
||||||
case wgpu::BufferBindingType::Storage:
|
case wgpu::BufferBindingType::Storage:
|
||||||
case wgpu::BufferBindingType::ReadOnlyStorage:
|
case wgpu::BufferBindingType::ReadOnlyStorage:
|
||||||
requiredUsage = wgpu::BufferUsage::Storage;
|
requiredUsage = wgpu::BufferUsage::Storage;
|
||||||
maxBindingSize = std::numeric_limits<uint64_t>::max();
|
maxBindingSize = kMaxStorageBufferBindingSize;
|
||||||
|
requiredBindingAlignment = kMinStorageBufferOffsetAlignment;
|
||||||
break;
|
break;
|
||||||
case kInternalStorageBufferBinding:
|
case kInternalStorageBufferBinding:
|
||||||
requiredUsage = kInternalStorageBuffer;
|
requiredUsage = kInternalStorageBuffer;
|
||||||
maxBindingSize = std::numeric_limits<uint64_t>::max();
|
maxBindingSize = kMaxStorageBufferBindingSize;
|
||||||
|
requiredBindingAlignment = kMinStorageBufferOffsetAlignment;
|
||||||
break;
|
break;
|
||||||
case wgpu::BufferBindingType::Undefined:
|
case wgpu::BufferBindingType::Undefined:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -85,9 +89,9 @@ namespace dawn_native {
|
|||||||
return DAWN_VALIDATION_ERROR("Buffer binding doesn't fit in the buffer");
|
return DAWN_VALIDATION_ERROR("Buffer binding doesn't fit in the buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsAligned(entry.offset, 256)) {
|
if (!IsAligned(entry.offset, requiredBindingAlignment)) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Buffer offset for bind group needs to be 256-byte aligned");
|
"Buffer offset for bind group needs to satisfy the minimum alignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(entry.buffer->GetUsage() & requiredUsage)) {
|
if (!(entry.buffer->GetUsage() & requiredUsage)) {
|
||||||
|
@ -123,7 +123,22 @@ namespace dawn_native {
|
|||||||
ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
|
ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
|
||||||
ASSERT(bindingInfo.buffer.hasDynamicOffset);
|
ASSERT(bindingInfo.buffer.hasDynamicOffset);
|
||||||
|
|
||||||
if (dynamicOffsets[i] % kMinDynamicBufferOffsetAlignment != 0) {
|
uint64_t requiredAlignment;
|
||||||
|
switch (bindingInfo.buffer.type) {
|
||||||
|
case wgpu::BufferBindingType::Uniform:
|
||||||
|
requiredAlignment = kMinUniformBufferOffsetAlignment;
|
||||||
|
break;
|
||||||
|
case wgpu::BufferBindingType::Storage:
|
||||||
|
case wgpu::BufferBindingType::ReadOnlyStorage:
|
||||||
|
case kInternalStorageBufferBinding:
|
||||||
|
requiredAlignment = kMinStorageBufferOffsetAlignment;
|
||||||
|
requiredAlignment = kMinStorageBufferOffsetAlignment;
|
||||||
|
break;
|
||||||
|
case wgpu::BufferBindingType::Undefined:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsAligned(dynamicOffsets[i], requiredAlignment)) {
|
||||||
return DAWN_VALIDATION_ERROR("Dynamic Buffer Offset need to be aligned");
|
return DAWN_VALIDATION_ERROR("Dynamic Buffer Offset need to be aligned");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,16 +39,16 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No underflow is possible because the max vertex format size is smaller than
|
// No underflow is possible because the max vertex format size is smaller than
|
||||||
// kMaxVertexBufferStride.
|
// kMaxVertexBufferArrayStride.
|
||||||
ASSERT(kMaxVertexBufferStride >= dawn::VertexFormatSize(attribute->format));
|
ASSERT(kMaxVertexBufferArrayStride >= dawn::VertexFormatSize(attribute->format));
|
||||||
if (attribute->offset >
|
if (attribute->offset >
|
||||||
kMaxVertexBufferStride - dawn::VertexFormatSize(attribute->format)) {
|
kMaxVertexBufferArrayStride - dawn::VertexFormatSize(attribute->format)) {
|
||||||
return DAWN_VALIDATION_ERROR("Setting attribute offset out of bounds");
|
return DAWN_VALIDATION_ERROR("Setting attribute offset out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
// No overflow is possible because the offset is already validated to be less
|
// No overflow is possible because the offset is already validated to be less
|
||||||
// than kMaxVertexBufferStride.
|
// than kMaxVertexBufferArrayStride.
|
||||||
ASSERT(attribute->offset < kMaxVertexBufferStride);
|
ASSERT(attribute->offset < kMaxVertexBufferArrayStride);
|
||||||
if (vertexBufferStride > 0 &&
|
if (vertexBufferStride > 0 &&
|
||||||
attribute->offset + dawn::VertexFormatSize(attribute->format) >
|
attribute->offset + dawn::VertexFormatSize(attribute->format) >
|
||||||
vertexBufferStride) {
|
vertexBufferStride) {
|
||||||
@ -73,7 +73,7 @@ namespace dawn_native {
|
|||||||
const VertexBufferLayout* buffer,
|
const VertexBufferLayout* buffer,
|
||||||
std::bitset<kMaxVertexAttributes>* attributesSetMask) {
|
std::bitset<kMaxVertexAttributes>* attributesSetMask) {
|
||||||
DAWN_TRY(ValidateInputStepMode(buffer->stepMode));
|
DAWN_TRY(ValidateInputStepMode(buffer->stepMode));
|
||||||
if (buffer->arrayStride > kMaxVertexBufferStride) {
|
if (buffer->arrayStride > kMaxVertexBufferArrayStride) {
|
||||||
return DAWN_VALIDATION_ERROR("Setting arrayStride out of bounds");
|
return DAWN_VALIDATION_ERROR("Setting arrayStride out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ namespace dawn_native { namespace null {
|
|||||||
|
|
||||||
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
||||||
|
|
||||||
static constexpr uint64_t kMaxMemoryUsage = 256 * 1024 * 1024;
|
static constexpr uint64_t kMaxMemoryUsage = 512 * 1024 * 1024;
|
||||||
size_t mMemoryUsage = 0;
|
size_t mMemoryUsage = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ TEST_P(BindGroupTests, SetDynamicBindGroupBeforePipeline) {
|
|||||||
std::array<float, 4> color0 = {1, 0, 0, 0.501};
|
std::array<float, 4> color0 = {1, 0, 0, 0.501};
|
||||||
std::array<float, 4> color1 = {0, 1, 0, 0.501};
|
std::array<float, 4> color1 = {0, 1, 0, 0.501};
|
||||||
|
|
||||||
size_t color1Offset = Align(sizeof(color0), kMinDynamicBufferOffsetAlignment);
|
size_t color1Offset = Align(sizeof(color0), kMinUniformBufferOffsetAlignment);
|
||||||
|
|
||||||
std::vector<uint8_t> data(color1Offset + sizeof(color1));
|
std::vector<uint8_t> data(color1Offset + sizeof(color1));
|
||||||
memcpy(data.data(), color0.data(), sizeof(color0));
|
memcpy(data.data(), color0.data(), sizeof(color0));
|
||||||
@ -612,7 +612,7 @@ TEST_P(BindGroupTests, BindGroupsPersistAfterPipelineChange) {
|
|||||||
std::array<float, 4> color0 = {1, 0, 0, 0.5};
|
std::array<float, 4> color0 = {1, 0, 0, 0.5};
|
||||||
std::array<float, 4> color1 = {0, 1, 0, 0.5};
|
std::array<float, 4> color1 = {0, 1, 0, 0.5};
|
||||||
|
|
||||||
size_t color1Offset = Align(sizeof(color0), kMinDynamicBufferOffsetAlignment);
|
size_t color1Offset = Align(sizeof(color0), kMinUniformBufferOffsetAlignment);
|
||||||
|
|
||||||
std::vector<uint8_t> data(color1Offset + sizeof(color1));
|
std::vector<uint8_t> data(color1Offset + sizeof(color1));
|
||||||
memcpy(data.data(), color0.data(), sizeof(color0));
|
memcpy(data.data(), color0.data(), sizeof(color0));
|
||||||
@ -699,9 +699,9 @@ TEST_P(BindGroupTests, DrawThenChangePipelineAndBindGroup) {
|
|||||||
std::array<float, 4> color2 = {0, 0, 0, 0.501};
|
std::array<float, 4> color2 = {0, 0, 0, 0.501};
|
||||||
std::array<float, 4> color3 = {0, 0, 1, 0};
|
std::array<float, 4> color3 = {0, 0, 1, 0};
|
||||||
|
|
||||||
size_t color1Offset = Align(sizeof(color0), kMinDynamicBufferOffsetAlignment);
|
size_t color1Offset = Align(sizeof(color0), kMinUniformBufferOffsetAlignment);
|
||||||
size_t color2Offset = Align(color1Offset + sizeof(color1), kMinDynamicBufferOffsetAlignment);
|
size_t color2Offset = Align(color1Offset + sizeof(color1), kMinUniformBufferOffsetAlignment);
|
||||||
size_t color3Offset = Align(color2Offset + sizeof(color2), kMinDynamicBufferOffsetAlignment);
|
size_t color3Offset = Align(color2Offset + sizeof(color2), kMinUniformBufferOffsetAlignment);
|
||||||
|
|
||||||
std::vector<uint8_t> data(color3Offset + sizeof(color3), 0);
|
std::vector<uint8_t> data(color3Offset + sizeof(color3), 0);
|
||||||
memcpy(data.data(), color0.data(), sizeof(color0));
|
memcpy(data.data(), color0.data(), sizeof(color0));
|
||||||
@ -773,14 +773,14 @@ TEST_P(BindGroupTests, DynamicOffsetOrder) {
|
|||||||
// We will put the following values and the respective offsets into a buffer.
|
// We will put the following values and the respective offsets into a buffer.
|
||||||
// The test will ensure that the correct dynamic offset is applied to each buffer by reading the
|
// The test will ensure that the correct dynamic offset is applied to each buffer by reading the
|
||||||
// value from an offset binding.
|
// value from an offset binding.
|
||||||
std::array<uint32_t, 3> offsets = {3 * kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 3> offsets = {3 * kMinUniformBufferOffsetAlignment,
|
||||||
1 * kMinDynamicBufferOffsetAlignment,
|
1 * kMinUniformBufferOffsetAlignment,
|
||||||
2 * kMinDynamicBufferOffsetAlignment};
|
2 * kMinUniformBufferOffsetAlignment};
|
||||||
std::array<uint32_t, 3> values = {21, 67, 32};
|
std::array<uint32_t, 3> values = {21, 67, 32};
|
||||||
|
|
||||||
// Create three buffers large enough to by offset by the largest offset.
|
// Create three buffers large enough to by offset by the largest offset.
|
||||||
wgpu::BufferDescriptor bufferDescriptor;
|
wgpu::BufferDescriptor bufferDescriptor;
|
||||||
bufferDescriptor.size = 3 * kMinDynamicBufferOffsetAlignment + sizeof(uint32_t);
|
bufferDescriptor.size = 3 * kMinUniformBufferOffsetAlignment + sizeof(uint32_t);
|
||||||
bufferDescriptor.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst;
|
bufferDescriptor.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst;
|
||||||
|
|
||||||
wgpu::Buffer buffer0 = device.CreateBuffer(&bufferDescriptor);
|
wgpu::Buffer buffer0 = device.CreateBuffer(&bufferDescriptor);
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
constexpr uint32_t kRTSize = 400;
|
constexpr uint32_t kRTSize = 400;
|
||||||
constexpr uint32_t kBufferElementsCount = kMinDynamicBufferOffsetAlignment / sizeof(uint32_t) + 2;
|
constexpr uint32_t kBufferElementsCount = kMinUniformBufferOffsetAlignment / sizeof(uint32_t) + 2;
|
||||||
constexpr uint32_t kBufferSize = kBufferElementsCount * sizeof(uint32_t);
|
constexpr uint32_t kBufferSize = kBufferElementsCount * sizeof(uint32_t);
|
||||||
constexpr uint32_t kBindingSize = 8;
|
constexpr uint32_t kBindingSize = 8;
|
||||||
|
|
||||||
@ -261,8 +261,8 @@ TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsRenderPipeline) {
|
|||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
std::array<uint32_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 2> offsets = {kMinUniformBufferOffsetAlignment,
|
||||||
kMinDynamicBufferOffsetAlignment};
|
kMinUniformBufferOffsetAlignment};
|
||||||
wgpu::RenderPassEncoder renderPassEncoder =
|
wgpu::RenderPassEncoder renderPassEncoder =
|
||||||
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
|
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
renderPassEncoder.SetPipeline(pipeline);
|
renderPassEncoder.SetPipeline(pipeline);
|
||||||
@ -275,7 +275,7 @@ TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsRenderPipeline) {
|
|||||||
std::vector<uint32_t> expectedData = {6, 8};
|
std::vector<uint32_t> expectedData = {6, 8};
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(5, 6, 255, 255), renderPass.color, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(5, 6, 255, 255), renderPass.color, 0, 0);
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
||||||
kMinDynamicBufferOffsetAlignment, expectedData.size());
|
kMinUniformBufferOffsetAlignment, expectedData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic offsets are all zero and no effect to result.
|
// Dynamic offsets are all zero and no effect to result.
|
||||||
@ -301,8 +301,8 @@ TEST_P(DynamicBufferOffsetTests, BasicComputePipeline) {
|
|||||||
TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsComputePipeline) {
|
TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsComputePipeline) {
|
||||||
wgpu::ComputePipeline pipeline = CreateComputePipeline();
|
wgpu::ComputePipeline pipeline = CreateComputePipeline();
|
||||||
|
|
||||||
std::array<uint32_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 2> offsets = {kMinUniformBufferOffsetAlignment,
|
||||||
kMinDynamicBufferOffsetAlignment};
|
kMinUniformBufferOffsetAlignment};
|
||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
||||||
@ -315,7 +315,7 @@ TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsComputePipeline) {
|
|||||||
|
|
||||||
std::vector<uint32_t> expectedData = {6, 8};
|
std::vector<uint32_t> expectedData = {6, 8};
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
||||||
kMinDynamicBufferOffsetAlignment, expectedData.size());
|
kMinUniformBufferOffsetAlignment, expectedData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test inherit dynamic offsets on render pipeline
|
// Test inherit dynamic offsets on render pipeline
|
||||||
@ -327,8 +327,8 @@ TEST_P(DynamicBufferOffsetTests, InheritDynamicOffestsRenderPipeline) {
|
|||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
std::array<uint32_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 2> offsets = {kMinUniformBufferOffsetAlignment,
|
||||||
kMinDynamicBufferOffsetAlignment};
|
kMinUniformBufferOffsetAlignment};
|
||||||
wgpu::RenderPassEncoder renderPassEncoder =
|
wgpu::RenderPassEncoder renderPassEncoder =
|
||||||
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
|
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
renderPassEncoder.SetPipeline(pipeline);
|
renderPassEncoder.SetPipeline(pipeline);
|
||||||
@ -344,7 +344,7 @@ TEST_P(DynamicBufferOffsetTests, InheritDynamicOffestsRenderPipeline) {
|
|||||||
std::vector<uint32_t> expectedData = {12, 16};
|
std::vector<uint32_t> expectedData = {12, 16};
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(5, 6, 255, 255), renderPass.color, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(5, 6, 255, 255), renderPass.color, 0, 0);
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
||||||
kMinDynamicBufferOffsetAlignment, expectedData.size());
|
kMinUniformBufferOffsetAlignment, expectedData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test inherit dynamic offsets on compute pipeline
|
// Test inherit dynamic offsets on compute pipeline
|
||||||
@ -356,8 +356,8 @@ TEST_P(DynamicBufferOffsetTests, InheritDynamicOffestsComputePipeline) {
|
|||||||
wgpu::ComputePipeline pipeline = CreateComputePipeline();
|
wgpu::ComputePipeline pipeline = CreateComputePipeline();
|
||||||
wgpu::ComputePipeline testPipeline = CreateComputePipeline(true);
|
wgpu::ComputePipeline testPipeline = CreateComputePipeline(true);
|
||||||
|
|
||||||
std::array<uint32_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 2> offsets = {kMinUniformBufferOffsetAlignment,
|
||||||
kMinDynamicBufferOffsetAlignment};
|
kMinUniformBufferOffsetAlignment};
|
||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
||||||
@ -373,7 +373,7 @@ TEST_P(DynamicBufferOffsetTests, InheritDynamicOffestsComputePipeline) {
|
|||||||
|
|
||||||
std::vector<uint32_t> expectedData = {12, 16};
|
std::vector<uint32_t> expectedData = {12, 16};
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffers[1],
|
||||||
kMinDynamicBufferOffsetAlignment, expectedData.size());
|
kMinUniformBufferOffsetAlignment, expectedData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting multiple dynamic offsets for the same bindgroup in one render pass.
|
// Setting multiple dynamic offsets for the same bindgroup in one render pass.
|
||||||
@ -384,8 +384,8 @@ TEST_P(DynamicBufferOffsetTests, UpdateDynamicOffestsMultipleTimesRenderPipeline
|
|||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
std::array<uint32_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 2> offsets = {kMinUniformBufferOffsetAlignment,
|
||||||
kMinDynamicBufferOffsetAlignment};
|
kMinUniformBufferOffsetAlignment};
|
||||||
std::array<uint32_t, 2> testOffsets = {0, 0};
|
std::array<uint32_t, 2> testOffsets = {0, 0};
|
||||||
|
|
||||||
wgpu::RenderPassEncoder renderPassEncoder =
|
wgpu::RenderPassEncoder renderPassEncoder =
|
||||||
@ -408,8 +408,8 @@ TEST_P(DynamicBufferOffsetTests, UpdateDynamicOffestsMultipleTimesRenderPipeline
|
|||||||
TEST_P(DynamicBufferOffsetTests, UpdateDynamicOffsetsMultipleTimesComputePipeline) {
|
TEST_P(DynamicBufferOffsetTests, UpdateDynamicOffsetsMultipleTimesComputePipeline) {
|
||||||
wgpu::ComputePipeline pipeline = CreateComputePipeline();
|
wgpu::ComputePipeline pipeline = CreateComputePipeline();
|
||||||
|
|
||||||
std::array<uint32_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
|
std::array<uint32_t, 2> offsets = {kMinUniformBufferOffsetAlignment,
|
||||||
kMinDynamicBufferOffsetAlignment};
|
kMinUniformBufferOffsetAlignment};
|
||||||
std::array<uint32_t, 2> testOffsets = {0, 0};
|
std::array<uint32_t, 2> testOffsets = {0, 0};
|
||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
@ -270,7 +270,7 @@ void DrawCallPerf::SetUp() {
|
|||||||
DawnPerfTestWithParams::SetUp();
|
DawnPerfTestWithParams::SetUp();
|
||||||
|
|
||||||
// Compute aligned uniform / vertex data sizes.
|
// Compute aligned uniform / vertex data sizes.
|
||||||
mAlignedUniformSize = Align(kUniformSize, kMinDynamicBufferOffsetAlignment);
|
mAlignedUniformSize = Align(kUniformSize, kMinUniformBufferOffsetAlignment);
|
||||||
mAlignedVertexDataSize = Align(sizeof(kVertexData), 4);
|
mAlignedVertexDataSize = Align(sizeof(kVertexData), 4);
|
||||||
|
|
||||||
// Initialize uniform buffer data.
|
// Initialize uniform buffer data.
|
||||||
|
@ -731,6 +731,36 @@ TEST_F(BindGroupValidationTest, MaxUniformBufferBindingSize) {
|
|||||||
utils::MakeBindGroup(device, storageLayout, {{0, buffer, 0, 2 * kMaxUniformBufferBindingSize}});
|
utils::MakeBindGroup(device, storageLayout, {{0, buffer, 0, 2 * kMaxUniformBufferBindingSize}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests constraints to be sure the storage buffer binding isn't too large
|
||||||
|
TEST_F(BindGroupValidationTest, MaxStorageBufferBindingSize) {
|
||||||
|
wgpu::BufferDescriptor descriptor;
|
||||||
|
descriptor.size = 2 * kMaxStorageBufferBindingSize;
|
||||||
|
descriptor.usage = wgpu::BufferUsage::Storage;
|
||||||
|
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||||
|
|
||||||
|
wgpu::BindGroupLayout uniformLayout = utils::MakeBindGroupLayout(
|
||||||
|
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage}});
|
||||||
|
|
||||||
|
// Success case, this is exactly the limit
|
||||||
|
utils::MakeBindGroup(device, uniformLayout, {{0, buffer, 0, kMaxStorageBufferBindingSize}});
|
||||||
|
|
||||||
|
// Success case, this is one less than the limit (check it is not an alignment constraint)
|
||||||
|
utils::MakeBindGroup(device, uniformLayout, {{0, buffer, 0, kMaxStorageBufferBindingSize - 1}});
|
||||||
|
|
||||||
|
wgpu::BindGroupLayout doubleUniformLayout = utils::MakeBindGroupLayout(
|
||||||
|
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage},
|
||||||
|
{1, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage}});
|
||||||
|
|
||||||
|
// Success case, individual bindings don't exceed the limit
|
||||||
|
utils::MakeBindGroup(device, doubleUniformLayout,
|
||||||
|
{{0, buffer, 0, kMaxStorageBufferBindingSize},
|
||||||
|
{1, buffer, kMaxStorageBufferBindingSize, kMaxStorageBufferBindingSize}});
|
||||||
|
|
||||||
|
// Error case, this is above the limit
|
||||||
|
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, uniformLayout,
|
||||||
|
{{0, buffer, 0, kMaxStorageBufferBindingSize + 1}}));
|
||||||
|
}
|
||||||
|
|
||||||
// Test what happens when the layout is an error.
|
// Test what happens when the layout is an error.
|
||||||
TEST_F(BindGroupValidationTest, ErrorLayout) {
|
TEST_F(BindGroupValidationTest, ErrorLayout) {
|
||||||
wgpu::BindGroupLayout goodLayout = utils::MakeBindGroupLayout(
|
wgpu::BindGroupLayout goodLayout = utils::MakeBindGroupLayout(
|
||||||
@ -1267,7 +1297,7 @@ TEST_F(BindGroupLayoutValidationTest, MultisampledTextureComponentType) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint64_t kBufferSize = 3 * kMinDynamicBufferOffsetAlignment + 8;
|
constexpr uint64_t kBufferSize = 3 * kMinUniformBufferOffsetAlignment + 8;
|
||||||
constexpr uint32_t kBindingSize = 9;
|
constexpr uint32_t kBindingSize = 9;
|
||||||
|
|
||||||
class SetBindGroupValidationTest : public ValidationTest {
|
class SetBindGroupValidationTest : public ValidationTest {
|
||||||
@ -1610,11 +1640,11 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetOrder) {
|
|||||||
// end of the buffer. Any mismatch applying too-large of an offset to a smaller buffer will hit
|
// end of the buffer. Any mismatch applying too-large of an offset to a smaller buffer will hit
|
||||||
// the out-of-bounds condition during validation.
|
// the out-of-bounds condition during validation.
|
||||||
wgpu::Buffer buffer3x =
|
wgpu::Buffer buffer3x =
|
||||||
CreateBuffer(3 * kMinDynamicBufferOffsetAlignment + 4, wgpu::BufferUsage::Storage);
|
CreateBuffer(3 * kMinUniformBufferOffsetAlignment + 4, wgpu::BufferUsage::Storage);
|
||||||
wgpu::Buffer buffer2x =
|
wgpu::Buffer buffer2x =
|
||||||
CreateBuffer(2 * kMinDynamicBufferOffsetAlignment + 4, wgpu::BufferUsage::Storage);
|
CreateBuffer(2 * kMinUniformBufferOffsetAlignment + 4, wgpu::BufferUsage::Storage);
|
||||||
wgpu::Buffer buffer1x =
|
wgpu::Buffer buffer1x =
|
||||||
CreateBuffer(1 * kMinDynamicBufferOffsetAlignment + 4, wgpu::BufferUsage::Uniform);
|
CreateBuffer(1 * kMinUniformBufferOffsetAlignment + 4, wgpu::BufferUsage::Uniform);
|
||||||
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl,
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl,
|
||||||
{
|
{
|
||||||
{0, buffer3x, 0, 4},
|
{0, buffer3x, 0, 4},
|
||||||
@ -1638,7 +1668,7 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetOrder) {
|
|||||||
// Offset the first binding to touch the end of the buffer. Should succeed.
|
// Offset the first binding to touch the end of the buffer. Should succeed.
|
||||||
// Will fail if the offset is applied to the first or second bindings since their buffers
|
// Will fail if the offset is applied to the first or second bindings since their buffers
|
||||||
// are too small.
|
// are too small.
|
||||||
offsets = {/* binding 0 */ 3 * kMinDynamicBufferOffsetAlignment,
|
offsets = {/* binding 0 */ 3 * kMinUniformBufferOffsetAlignment,
|
||||||
/* binding 2 */ 0,
|
/* binding 2 */ 0,
|
||||||
/* binding 3 */ 0};
|
/* binding 3 */ 0};
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
@ -1650,7 +1680,7 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetOrder) {
|
|||||||
{
|
{
|
||||||
// Offset the second binding to touch the end of the buffer. Should succeed.
|
// Offset the second binding to touch the end of the buffer. Should succeed.
|
||||||
offsets = {/* binding 0 */ 0,
|
offsets = {/* binding 0 */ 0,
|
||||||
/* binding 2 */ 1 * kMinDynamicBufferOffsetAlignment,
|
/* binding 2 */ 1 * kMinUniformBufferOffsetAlignment,
|
||||||
/* binding 3 */ 0};
|
/* binding 3 */ 0};
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
||||||
@ -1664,7 +1694,7 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetOrder) {
|
|||||||
// is too small.
|
// is too small.
|
||||||
offsets = {/* binding 0 */ 0,
|
offsets = {/* binding 0 */ 0,
|
||||||
/* binding 2 */ 0,
|
/* binding 2 */ 0,
|
||||||
/* binding 3 */ 2 * kMinDynamicBufferOffsetAlignment};
|
/* binding 3 */ 2 * kMinUniformBufferOffsetAlignment};
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
||||||
computePassEncoder.SetBindGroup(0, bindGroup, offsets.size(), offsets.data());
|
computePassEncoder.SetBindGroup(0, bindGroup, offsets.size(), offsets.data());
|
||||||
@ -1673,9 +1703,9 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetOrder) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Offset each binding to touch the end of their buffer. Should succeed.
|
// Offset each binding to touch the end of their buffer. Should succeed.
|
||||||
offsets = {/* binding 0 */ 3 * kMinDynamicBufferOffsetAlignment,
|
offsets = {/* binding 0 */ 3 * kMinUniformBufferOffsetAlignment,
|
||||||
/* binding 2 */ 1 * kMinDynamicBufferOffsetAlignment,
|
/* binding 2 */ 1 * kMinUniformBufferOffsetAlignment,
|
||||||
/* binding 3 */ 2 * kMinDynamicBufferOffsetAlignment};
|
/* binding 3 */ 2 * kMinUniformBufferOffsetAlignment};
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
|
||||||
computePassEncoder.SetBindGroup(0, bindGroup, offsets.size(), offsets.data());
|
computePassEncoder.SetBindGroup(0, bindGroup, offsets.size(), offsets.data());
|
||||||
|
@ -101,45 +101,30 @@ namespace {
|
|||||||
|
|
||||||
// Test OOB color attachment indices are handled
|
// Test OOB color attachment indices are handled
|
||||||
TEST_F(RenderPassDescriptorValidationTest, ColorAttachmentOutOfBounds) {
|
TEST_F(RenderPassDescriptorValidationTest, ColorAttachmentOutOfBounds) {
|
||||||
wgpu::TextureView color0 =
|
std::array<wgpu::RenderPassColorAttachmentDescriptor, kMaxColorAttachments + 1>
|
||||||
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
|
colorAttachments;
|
||||||
wgpu::TextureView color1 =
|
for (uint32_t i = 0; i < colorAttachments.size(); i++) {
|
||||||
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
|
colorAttachments[i].view =
|
||||||
wgpu::TextureView color2 =
|
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
|
||||||
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
|
colorAttachments[i].resolveTarget = nullptr;
|
||||||
wgpu::TextureView color3 =
|
colorAttachments[i].clearColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
|
colorAttachments[i].loadOp = wgpu::LoadOp::Clear;
|
||||||
// For setting the color attachment, control case
|
colorAttachments[i].storeOp = wgpu::StoreOp::Store;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Control case: kMaxColorAttachments is valid.
|
||||||
{
|
{
|
||||||
utils::ComboRenderPassDescriptor renderPass({color0, color1, color2, color3});
|
wgpu::RenderPassDescriptor renderPass;
|
||||||
|
renderPass.colorAttachmentCount = kMaxColorAttachments;
|
||||||
|
renderPass.colorAttachments = colorAttachments.data();
|
||||||
|
renderPass.depthStencilAttachment = nullptr;
|
||||||
AssertBeginRenderPassSuccess(&renderPass);
|
AssertBeginRenderPassSuccess(&renderPass);
|
||||||
}
|
}
|
||||||
// For setting the color attachment, OOB
|
|
||||||
|
// Error case: kMaxColorAttachments + 1 is an error.
|
||||||
{
|
{
|
||||||
// We cannot use utils::ComboRenderPassDescriptor here because it only supports at most
|
|
||||||
// kMaxColorAttachments(4) color attachments.
|
|
||||||
std::array<wgpu::RenderPassColorAttachmentDescriptor, 5> colorAttachments;
|
|
||||||
colorAttachments[0].view = color0;
|
|
||||||
colorAttachments[0].resolveTarget = nullptr;
|
|
||||||
colorAttachments[0].clearColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
||||||
colorAttachments[0].loadOp = wgpu::LoadOp::Clear;
|
|
||||||
colorAttachments[0].storeOp = wgpu::StoreOp::Store;
|
|
||||||
|
|
||||||
colorAttachments[1] = colorAttachments[0];
|
|
||||||
colorAttachments[1].view = color1;
|
|
||||||
|
|
||||||
colorAttachments[2] = colorAttachments[0];
|
|
||||||
colorAttachments[2].view = color2;
|
|
||||||
|
|
||||||
colorAttachments[3] = colorAttachments[0];
|
|
||||||
colorAttachments[3].view = color3;
|
|
||||||
|
|
||||||
colorAttachments[4] = colorAttachments[0];
|
|
||||||
colorAttachments[4].view =
|
|
||||||
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
|
|
||||||
|
|
||||||
wgpu::RenderPassDescriptor renderPass;
|
wgpu::RenderPassDescriptor renderPass;
|
||||||
renderPass.colorAttachmentCount = 5;
|
renderPass.colorAttachmentCount = kMaxColorAttachments + 1;
|
||||||
renderPass.colorAttachments = colorAttachments.data();
|
renderPass.colorAttachments = colorAttachments.data();
|
||||||
renderPass.depthStencilAttachment = nullptr;
|
renderPass.depthStencilAttachment = nullptr;
|
||||||
AssertBeginRenderPassError(&renderPass);
|
AssertBeginRenderPassError(&renderPass);
|
||||||
|
@ -199,12 +199,12 @@ TEST_F(VertexStateTest, SetInputStrideOutOfBounds) {
|
|||||||
// Control case, setting max input arrayStride
|
// Control case, setting max input arrayStride
|
||||||
utils::ComboVertexStateDescriptor state;
|
utils::ComboVertexStateDescriptor state;
|
||||||
state.vertexBufferCount = 1;
|
state.vertexBufferCount = 1;
|
||||||
state.cVertexBuffers[0].arrayStride = kMaxVertexBufferStride;
|
state.cVertexBuffers[0].arrayStride = kMaxVertexBufferArrayStride;
|
||||||
state.cVertexBuffers[0].attributeCount = 1;
|
state.cVertexBuffers[0].attributeCount = 1;
|
||||||
CreatePipeline(true, state, kDummyVertexShader);
|
CreatePipeline(true, state, kDummyVertexShader);
|
||||||
|
|
||||||
// Test input arrayStride OOB
|
// Test input arrayStride OOB
|
||||||
state.cVertexBuffers[0].arrayStride = kMaxVertexBufferStride + 1;
|
state.cVertexBuffers[0].arrayStride = kMaxVertexBufferArrayStride + 1;
|
||||||
CreatePipeline(false, state, kDummyVertexShader);
|
CreatePipeline(false, state, kDummyVertexShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,11 +283,11 @@ TEST_F(VertexStateTest, SetAttributeOffsetOutOfBounds) {
|
|||||||
utils::ComboVertexStateDescriptor state;
|
utils::ComboVertexStateDescriptor state;
|
||||||
state.vertexBufferCount = 1;
|
state.vertexBufferCount = 1;
|
||||||
state.cVertexBuffers[0].attributeCount = 1;
|
state.cVertexBuffers[0].attributeCount = 1;
|
||||||
state.cAttributes[0].offset = kMaxVertexBufferStride - sizeof(wgpu::VertexFormat::Float32);
|
state.cAttributes[0].offset = kMaxVertexBufferArrayStride - sizeof(wgpu::VertexFormat::Float32);
|
||||||
CreatePipeline(true, state, kDummyVertexShader);
|
CreatePipeline(true, state, kDummyVertexShader);
|
||||||
|
|
||||||
// Test attribute offset out of bounds
|
// Test attribute offset out of bounds
|
||||||
state.cAttributes[0].offset = kMaxVertexBufferStride - 1;
|
state.cAttributes[0].offset = kMaxVertexBufferArrayStride - 1;
|
||||||
CreatePipeline(false, state, kDummyVertexShader);
|
CreatePipeline(false, state, kDummyVertexShader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user