diff --git a/src/tests/end2end/BindGroupTests.cpp b/src/tests/end2end/BindGroupTests.cpp index eb316243f7..a47388dccb 100644 --- a/src/tests/end2end/BindGroupTests.cpp +++ b/src/tests/end2end/BindGroupTests.cpp @@ -45,11 +45,17 @@ class BindGroupTests : public DawnTest { } wgpu::ShaderModule MakeSimpleVSModule() const { - return utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( - #version 450 - void main() { - const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f)); - gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f); + return utils::CreateShaderModuleFromWGSL(device, R"( + [[builtin(vertex_idx)]] var VertexIndex : u32; + [[builtin(position)]] var Position : vec4; + + [[stage(vertex)]] fn main() -> void { + const pos : array, 3> = array, 3>( + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0)); + + Position = vec4(pos[VertexIndex], 0.0, 1.0); })"); } @@ -57,43 +63,33 @@ class BindGroupTests : public DawnTest { ASSERT(bindingTypes.size() <= kMaxBindGroups); std::ostringstream fs; - fs << R"( - #version 450 - layout(location = 0) out vec4 fragColor; - )"; + fs << "[[location(0)]] var fragColor : vec4;\n"; for (size_t i = 0; i < bindingTypes.size(); ++i) { + fs << "[[block]] struct Buffer" << i << R"( { + [[offset(0)]] color : vec4; + };)"; + switch (bindingTypes[i]) { case wgpu::BufferBindingType::Uniform: - fs << "layout (std140, set = " << i << ", binding = 0) uniform UniformBuffer" - << i << R"( { - vec4 color; - } buffer)" - << i << ";\n"; + fs << "\n[[set(" << i << "), binding(0)]] var buffer" << i + << " : Buffer" << i << ";"; break; case wgpu::BufferBindingType::Storage: - fs << "layout (std430, set = " << i << ", binding = 0) buffer StorageBuffer" - << i << R"( { - vec4 color; - } buffer)" - << i << ";\n"; + fs << "\n[[set(" << i << "), binding(0)]] var buffer" << i + << " : [[access(read)]] Buffer" << i << ";"; break; default: UNREACHABLE(); } } - fs << R"( - void main() { - fragColor = vec4(0.0); - )"; + fs << "\n[[stage(fragment)]] fn main() -> void {\n"; for (size_t i = 0; i < bindingTypes.size(); ++i) { - fs << "fragColor += buffer" << i << ".color;\n"; + fs << "fragColor = fragColor + buffer" << i << ".color;\n"; } fs << "}\n"; - - return utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, - fs.str().c_str()); + return utils::CreateShaderModuleFromWGSL(device, fs.str().c_str()); } wgpu::RenderPipeline MakeTestPipeline(const utils::BasicRenderPass& renderPass, @@ -123,17 +119,14 @@ class BindGroupTests : public DawnTest { // Test a bindgroup reused in two command buffers in the same call to queue.Submit(). // This test passes by not asserting or crashing. TEST_P(BindGroupTests, ReusedBindGroupSingleSubmit) { - const char* shader = R"( - #version 450 - layout(std140, set = 0, binding = 0) uniform Contents { - float f; - } contents; - void main() { - } - )"; + wgpu::ShaderModule module = utils::CreateShaderModuleFromWGSL(device, R"( + [[block]] struct Contents { + [[offset(0)]] f : f32; + }; + [[set(0), binding(0)]] var contents: Contents; - wgpu::ShaderModule module = - utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, shader); + [[stage(compute)]] fn main() -> void { + })"); wgpu::ComputePipelineDescriptor cpDesc; cpDesc.computeStage.module = module; @@ -163,26 +156,39 @@ TEST_P(BindGroupTests, ReusedUBO) { utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize); - wgpu::ShaderModule vsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( - #version 450 - layout (set = 0, binding = 0) uniform vertexUniformBuffer { - mat2 transform; + wgpu::ShaderModule vsModule = utils::CreateShaderModuleFromWGSL(device, R"( + # TODO(crbug.com/tint/369): Use a mat2x2 when Tint translates it correctly. + [[block]] struct VertexUniformBuffer { + [[offset(0)]] transform : vec4; }; - void main() { - const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f)); - gl_Position = vec4(transform * pos[gl_VertexIndex], 0.f, 1.f); + + [[set(0), binding(0)]] var vertexUbo : VertexUniformBuffer; + + [[builtin(vertex_idx)]] var VertexIndex : u32; + [[builtin(position)]] var Position : vec4; + + [[stage(vertex)]] fn main() -> void { + const pos : array, 3> = array, 3>( + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0)); + + var transform : mat2x2 = mat2x2( + vec2(vertexUbo.transform[0], vertexUbo.transform[1]), + vec2(vertexUbo.transform[2], vertexUbo.transform[3])); + Position = vec4(transform * pos[VertexIndex], 0.0, 1.0); })"); - wgpu::ShaderModule fsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( - #version 450 - layout (set = 0, binding = 1) uniform fragmentUniformBuffer { - vec4 color; + wgpu::ShaderModule fsModule = utils::CreateShaderModuleFromWGSL(device, R"( + [[block]] struct FragmentUniformBuffer { + [[offset(0)]] color : vec4; }; - layout(location = 0) out vec4 fragColor; - void main() { - fragColor = color; + [[set(0), binding(1)]] var fragmentUbo : FragmentUniformBuffer; + + [[location(0)]] var fragColor : vec4; + + [[stage(fragment)]] fn main() -> void { + fragColor = fragmentUbo.color; })"); utils::ComboRenderPipelineDescriptor textureDescriptor(device); @@ -198,9 +204,8 @@ TEST_P(BindGroupTests, ReusedUBO) { float color[4]; }; ASSERT(offsetof(Data, color) == 256); - constexpr float dummy = 0.0f; Data data{ - {1.f, 0.f, dummy, dummy, 0.f, 1.0f, dummy, dummy}, + {1.f, 0.f, 0.f, 1.0f}, {0}, {0.f, 1.f, 0.f, 1.f}, }; @@ -239,25 +244,37 @@ TEST_P(BindGroupTests, UBOSamplerAndTexture) { utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize); - wgpu::ShaderModule vsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( - #version 450 - layout (set = 0, binding = 0) uniform vertexUniformBuffer { - mat2 transform; + wgpu::ShaderModule vsModule = utils::CreateShaderModuleFromWGSL(device, R"( + # TODO(crbug.com/tint/369): Use a mat2x2 when Tint translates it correctly. + [[block]] struct VertexUniformBuffer { + [[offset(0)]] transform : vec4; }; - void main() { - const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f)); - gl_Position = vec4(transform * pos[gl_VertexIndex], 0.f, 1.f); + [[set(0), binding(0)]] var vertexUbo : VertexUniformBuffer; + + [[builtin(vertex_idx)]] var VertexIndex : u32; + [[builtin(position)]] var Position : vec4; + + [[stage(vertex)]] fn main() -> void { + const pos : array, 3> = array, 3>( + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0)); + + var transform : mat2x2 = mat2x2( + vec2(vertexUbo.transform[0], vertexUbo.transform[1]), + vec2(vertexUbo.transform[2], vertexUbo.transform[3])); + Position = vec4(transform * pos[VertexIndex], 0.0, 1.0); })"); - wgpu::ShaderModule fsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( - #version 450 - layout (set = 0, binding = 1) uniform sampler samp; - layout (set = 0, binding = 2) uniform texture2D tex; - layout (location = 0) out vec4 fragColor; - void main() { - fragColor = texture(sampler2D(tex, samp), gl_FragCoord.xy); + wgpu::ShaderModule fsModule = utils::CreateShaderModuleFromWGSL(device, R"( + [[set(0), binding(1)]] var samp : sampler; + [[set(0), binding(2)]] var tex : texture_2d; + [[builtin(frag_coord)]] var FragCoord : vec4; + + [[location(0)]] var fragColor : vec4; + + [[stage(fragment)]] fn main() -> void { + fragColor = textureSample(tex, samp, FragCoord.xy); })"); utils::ComboRenderPipelineDescriptor pipelineDescriptor(device); @@ -267,8 +284,7 @@ TEST_P(BindGroupTests, UBOSamplerAndTexture) { wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor); - constexpr float dummy = 0.0f; - constexpr float transform[] = {1.f, 0.f, dummy, dummy, 0.f, 1.f, dummy, dummy}; + constexpr float transform[] = {1.f, 0.f, 0.f, 1.f}; wgpu::Buffer buffer = utils::CreateBufferFromData(device, &transform, sizeof(transform), wgpu::BufferUsage::Uniform); @@ -343,32 +359,54 @@ TEST_P(BindGroupTests, MultipleBindLayouts) { utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize); - wgpu::ShaderModule vsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( - #version 450 - layout (set = 0, binding = 0) uniform vertexUniformBuffer1 { - mat2 transform1; + wgpu::ShaderModule vsModule = utils::CreateShaderModuleFromWGSL(device, R"( + # TODO(crbug.com/tint/369): Use a mat2x2 when Tint translates it correctly. + # TODO(crbug.com/tint/386): Use the same struct. + [[block]] struct VertexUniformBuffer1 { + [[offset(0)]] transform : vec4; }; - layout (set = 1, binding = 0) uniform vertexUniformBuffer2 { - mat2 transform2; + + [[block]] struct VertexUniformBuffer2 { + [[offset(0)]] transform : vec4; }; - void main() { - const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f)); - gl_Position = vec4((transform1 + transform2) * pos[gl_VertexIndex], 0.f, 1.f); + + # TODO(crbug.com/tint/386): Use the same struct definition. + [[set(0), binding(0)]] var vertexUbo1 : VertexUniformBuffer1; + [[set(1), binding(0)]] var vertexUbo2 : VertexUniformBuffer2; + + [[builtin(vertex_idx)]] var VertexIndex : u32; + [[builtin(position)]] var Position : vec4; + + [[stage(vertex)]] fn main() -> void { + const pos : array, 3> = array, 3>( + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0)); + + Position = vec4(mat2x2( + vertexUbo1.transform.xy + vertexUbo2.transform.xy, + vertexUbo1.transform.zw + vertexUbo2.transform.zw + ) * pos[VertexIndex], 0.0, 1.0); })"); - wgpu::ShaderModule fsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( - #version 450 - layout (set = 0, binding = 1) uniform fragmentUniformBuffer1 { - vec4 color1; + wgpu::ShaderModule fsModule = utils::CreateShaderModuleFromWGSL(device, R"( + # TODO(crbug.com/tint/386): Use the same struct + [[block]] struct FragmentUniformBuffer1 { + [[offset(0)]] color : vec4; }; - layout (set = 1, binding = 1) uniform fragmentUniformBuffer2 { - vec4 color2; + + [[block]] struct FragmentUniformBuffer2 { + [[offset(0)]] color : vec4; }; - layout(location = 0) out vec4 fragColor; - void main() { - fragColor = color1 + color2; + + # TODO(crbug.com/tint/386): Use the same struct definition. + [[set(0), binding(1)]] var fragmentUbo1 : FragmentUniformBuffer1; + [[set(1), binding(1)]] var fragmentUbo2 : FragmentUniformBuffer2; + + [[location(0)]] var fragColor : vec4; + + [[stage(fragment)]] fn main() -> void { + fragColor = fragmentUbo1.color + fragmentUbo2.color; })"); utils::ComboRenderPipelineDescriptor textureDescriptor(device); @@ -379,8 +417,8 @@ TEST_P(BindGroupTests, MultipleBindLayouts) { wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor); struct Data { - float transform[8]; - char padding[256 - 8 * sizeof(float)]; + float transform[4]; + char padding[256 - 4 * sizeof(float)]; float color[4]; }; ASSERT(offsetof(Data, color) == 256); @@ -389,11 +427,9 @@ TEST_P(BindGroupTests, MultipleBindLayouts) { std::vector buffers; std::vector bindGroups; - data.push_back( - {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, {0}, {0.0f, 1.0f, 0.0f, 1.0f}}); + data.push_back({{1.0f, 0.0f, 0.0f, 0.0f}, {0}, {0.0f, 1.0f, 0.0f, 1.0f}}); - data.push_back( - {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, {0}, {1.0f, 0.0f, 0.0f, 1.0f}}); + data.push_back({{0.0f, 0.0f, 0.0f, 1.0f}, {0}, {1.0f, 0.0f, 0.0f, 1.0f}}); for (int i = 0; i < 2; i++) { wgpu::Buffer buffer = @@ -809,25 +845,32 @@ TEST_P(BindGroupTests, DynamicOffsetOrder) { }); wgpu::ComputePipelineDescriptor pipelineDescriptor; - pipelineDescriptor.computeStage.module = - utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"( - #version 450 - layout(std140, set = 0, binding = 2) uniform Buffer2 { - uint value2; + pipelineDescriptor.computeStage.module = utils::CreateShaderModuleFromWGSL(device, R"( + # TODO(crbug.com/tint/386): Use the same struct + [[block]] struct Buffer0 { + [[offset(0)]] value : u32; }; - layout(std430, set = 0, binding = 3) readonly buffer Buffer3 { - uint value3; + + [[block]] struct Buffer2 { + [[offset(0)]] value : u32; }; - layout(std430, set = 0, binding = 0) readonly buffer Buffer0 { - uint value0; + + [[block]] struct Buffer3 { + [[offset(0)]] value : u32; }; - layout(std430, set = 0, binding = 4) buffer OutputBuffer { - uvec3 outputBuffer; + + [[block]] struct OutputBuffer { + [[offset(0)]] value : vec3; }; - void main() { - outputBuffer = uvec3(value0, value2, value3); - } - )"); + + [[set(0), binding(2)]] var buffer2 : Buffer2; + [[set(0), binding(3)]] var buffer3 : [[access(read)]] Buffer3; + [[set(0), binding(0)]] var buffer0 : [[access(read)]] Buffer0; + [[set(0), binding(4)]] var outputBuffer : [[access(read_write)]] OutputBuffer; + + [[stage(compute)]] fn main() -> void { + outputBuffer.value = vec3(buffer0.value, buffer2.value, buffer3.value); + })"); pipelineDescriptor.computeStage.entryPoint = "main"; pipelineDescriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl); wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDescriptor); @@ -917,29 +960,42 @@ TEST_P(BindGroupTests, DynamicBindingNoneVisibility) { TEST_P(BindGroupTests, ArbitraryBindingNumbers) { utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize); - wgpu::ShaderModule vsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( - #version 450 - void main() { - const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f)); - gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f); + wgpu::ShaderModule vsModule = utils::CreateShaderModuleFromWGSL(device, R"( + [[builtin(vertex_idx)]] var VertexIndex : u32; + [[builtin(position)]] var Position : vec4; + + [[stage(vertex)]] fn main() -> void { + const pos : array, 3> = array, 3>( + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0)); + + Position = vec4(pos[VertexIndex], 0.0, 1.0); })"); - wgpu::ShaderModule fsModule = - utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( - #version 450 - layout (set = 0, binding = 953) uniform ubo1 { - vec4 color1; + wgpu::ShaderModule fsModule = utils::CreateShaderModuleFromWGSL(device, R"( + # TODO(crbug.com/tint/386): Use the same struct + [[block]] struct Ubo1 { + [[offset(0)]] color : vec4; }; - layout (set = 0, binding = 47) uniform ubo2 { - vec4 color2; + + [[block]] struct Ubo2 { + [[offset(0)]] color : vec4; }; - layout (set = 0, binding = 111) uniform ubo3 { - vec4 color3; + + [[block]] struct Ubo3 { + [[offset(0)]] color : vec4; }; - layout(location = 0) out vec4 fragColor; - void main() { - fragColor = color1 + 2 * color2 + 4 * color3; + + # TODO(crbug.com/tint/386): Use the same struct definition. + [[set(0), binding(953)]] var ubo1 : Ubo1; + [[set(0), binding(47)]] var ubo2 : Ubo2; + [[set(0), binding(111)]] var ubo3 : Ubo3; + + [[location(0)]] var fragColor : vec4; + + [[stage(fragment)]] fn main() -> void { + fragColor = ubo1.color + 2.0 * ubo2.color + 4.0 * ubo3.color; })"); utils::ComboRenderPipelineDescriptor pipelineDescriptor(device); @@ -1037,10 +1093,8 @@ TEST_P(BindGroupTests, EmptyLayout) { wgpu::ComputePipelineDescriptor pipelineDesc; pipelineDesc.layout = utils::MakeBasicPipelineLayout(device, &bgl); pipelineDesc.computeStage.entryPoint = "main"; - pipelineDesc.computeStage.module = - utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"( - #version 450 - void main() { + pipelineDesc.computeStage.module = utils::CreateShaderModuleFromWGSL(device, R"( + [[stage(compute)]] fn main() -> void { })"); wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDesc); @@ -1062,24 +1116,29 @@ TEST_P(BindGroupTests, EmptyLayout) { TEST_P(BindGroupTests, ReadonlyStorage) { utils::ComboRenderPipelineDescriptor pipelineDescriptor(device); - pipelineDescriptor.vertexStage.module = - utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( - #version 450 - void main() { - const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f)); - gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f); - })"); + pipelineDescriptor.vertexStage.module = utils::CreateShaderModuleFromWGSL(device, R"( + [[builtin(vertex_idx)]] var VertexIndex : u32; + [[builtin(position)]] var Position : vec4; - pipelineDescriptor.cFragmentStage.module = - utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( - #version 450 - layout(set = 0, binding = 0) readonly buffer buffer0 { - vec4 color; - }; - layout(location = 0) out vec4 fragColor; - void main() { - fragColor = color; - })"); + [[stage(vertex)]] fn main() -> void { + const pos : array, 3> = array, 3>( + vec2(-1.0, 1.0), + vec2( 1.0, 1.0), + vec2(-1.0, -1.0)); + + Position = vec4(pos[VertexIndex], 0.0, 1.0); + })"); + + pipelineDescriptor.cFragmentStage.module = utils::CreateShaderModuleFromWGSL(device, R"( + [[block]] struct Buffer0 { + [[offset(0)]] color : vec4; + }; + [[set(0), binding(0)]] var buffer0 : [[access(read)]] Buffer0; + + [[location(0)]] var fragColor : vec4; + [[stage(fragment)]] fn main() -> void { + fragColor = buffer0.color; + })"); constexpr uint32_t kRTSize = 4; utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize); @@ -1115,22 +1174,27 @@ TEST_P(BindGroupTests, ReadonlyStorage) { // buffer if all values are correct. TEST_P(BindGroupTests, ReallyLargeBindGroup) { DAWN_SKIP_TEST_IF(IsOpenGLES()); - std::string interface = "#version 450\n"; - std::string body; + std::ostringstream interface; + std::ostringstream body; uint32_t binding = 0; uint32_t expectedValue = 42; wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder(); - auto CreateTextureWithRedData = [&](uint32_t value, wgpu::TextureUsage usage) { + auto CreateTextureWithRedData = [&](wgpu::TextureFormat format, uint32_t value, + wgpu::TextureUsage usage) { wgpu::TextureDescriptor textureDesc = {}; textureDesc.usage = wgpu::TextureUsage::CopyDst | usage; textureDesc.size = {1, 1, 1}; - textureDesc.format = wgpu::TextureFormat::R32Uint; + textureDesc.format = format; wgpu::Texture texture = device.CreateTexture(&textureDesc); + if (format == wgpu::TextureFormat::R8Unorm) { + ASSERT(expectedValue < 255u); + } wgpu::Buffer textureData = - utils::CreateBufferFromData(device, wgpu::BufferUsage::CopySrc, {expectedValue}); + utils::CreateBufferFromData(device, wgpu::BufferUsage::CopySrc, {value}); + wgpu::BufferCopyView bufferCopyView = {}; bufferCopyView.buffer = textureData; bufferCopyView.layout.bytesPerRow = 256; @@ -1147,52 +1211,55 @@ TEST_P(BindGroupTests, ReallyLargeBindGroup) { std::vector bgEntries; static_assert(kMaxSampledTexturesPerShaderStage == kMaxSamplersPerShaderStage, "Please update this test"); - body += "result = 0;\n"; for (uint32_t i = 0; i < kMaxSampledTexturesPerShaderStage; ++i) { - wgpu::Texture texture = - CreateTextureWithRedData(expectedValue, wgpu::TextureUsage::Sampled); + wgpu::Texture texture = CreateTextureWithRedData( + wgpu::TextureFormat::R8Unorm, expectedValue, wgpu::TextureUsage::Sampled); bgEntries.push_back({binding, nullptr, 0, 0, nullptr, texture.CreateView()}); - interface += "layout(set = 0, binding = " + std::to_string(binding++) + - ") uniform utexture2D tex" + std::to_string(i) + ";\n"; + interface << "[[set(0), binding(" << binding++ << ")]] " + << "var tex" << i << " : texture_2d;\n"; wgpu::SamplerDescriptor samplerDesc = {}; bgEntries.push_back({binding, nullptr, 0, 0, device.CreateSampler(&samplerDesc), nullptr}); - interface += "layout(set = 0, binding = " + std::to_string(binding++) + - ") uniform sampler samp" + std::to_string(i) + ";\n"; + interface << "[[set(0), binding(" << binding++ << ")]]" + << "var samp" << i << " : sampler;\n"; - body += "if (texelFetch(usampler2D(tex" + std::to_string(i) + ", samp" + std::to_string(i) + - "), ivec2(0, 0), 0).r != " + std::to_string(expectedValue++) + ") {\n"; - body += " return;\n"; - body += "}\n"; + body << "if (abs(textureSampleLevel(tex" << i << ", samp" << i + << ", vec2(0.5, 0.5), 0.0).r - " << expectedValue++ + << ".0 / 255.0) > 0.0001) {\n"; + body << " return;\n"; + body << "}\n"; } for (uint32_t i = 0; i < kMaxStorageTexturesPerShaderStage; ++i) { - wgpu::Texture texture = - CreateTextureWithRedData(expectedValue, wgpu::TextureUsage::Storage); + wgpu::Texture texture = CreateTextureWithRedData( + wgpu::TextureFormat::R32Uint, expectedValue, wgpu::TextureUsage::Storage); bgEntries.push_back({binding, nullptr, 0, 0, nullptr, texture.CreateView()}); - interface += "layout(set = 0, binding = " + std::to_string(binding++) + - ", r32ui) uniform readonly uimage2D image" + std::to_string(i) + ";\n"; + interface << "[[set(0), binding(" << binding++ << ")]] " + << "var image" << i << " : texture_storage_ro_2d;\n"; - body += "if (imageLoad(image" + std::to_string(i) + - ", ivec2(0, 0)).r != " + std::to_string(expectedValue++) + ") {\n"; - body += " return;\n"; - body += "}\n"; + body << "if (textureLoad(image" << i << ", vec2(0, 0)).r != " << expectedValue++ + << "u) {\n"; + body << " return;\n"; + body << "}\n"; } + for (uint32_t i = 0; i < kMaxUniformBuffersPerShaderStage; ++i) { wgpu::Buffer buffer = utils::CreateBufferFromData( device, wgpu::BufferUsage::Uniform, {expectedValue, 0, 0, 0}); bgEntries.push_back({binding, buffer, 0, 4 * sizeof(uint32_t), nullptr, nullptr}); - interface += "layout(std140, set = 0, binding = " + std::to_string(binding++) + - ") uniform UBuf" + std::to_string(i) + " {\n"; - interface += " uint ubuf" + std::to_string(i) + ";\n"; - interface += "};\n"; + interface << "[[block]] struct UniformBuffer" << i << R"({ + [[offset(0)]] value : u32; + }; + )"; + interface << "[[set(0), binding(" << binding++ << ")]] " + << "var ubuf" << i << " : UniformBuffer" << i << ";\n"; - body += "if (ubuf" + std::to_string(i) + " != " + std::to_string(expectedValue++) + ") {\n"; - body += " return;\n"; - body += "}\n"; + body << "if (ubuf" << i << ".value != " << expectedValue++ << "u) {\n"; + body << " return;\n"; + body << "}\n"; } // Save one storage buffer for writing the result for (uint32_t i = 0; i < kMaxStorageBuffersPerShaderStage - 1; ++i) { @@ -1200,32 +1267,36 @@ TEST_P(BindGroupTests, ReallyLargeBindGroup) { device, wgpu::BufferUsage::Storage, {expectedValue}); bgEntries.push_back({binding, buffer, 0, sizeof(uint32_t), nullptr, nullptr}); - interface += "layout(std430, set = 0, binding = " + std::to_string(binding++) + - ") readonly buffer SBuf" + std::to_string(i) + " {\n"; - interface += " uint sbuf" + std::to_string(i) + ";\n"; - interface += "};\n"; + interface << "[[block]] struct ReadOnlyStorageBuffer" << i << R"({ + [[offset(0)]] value : u32; + }; + )"; + interface << "[[set(0), binding(" << binding++ << ")]] " + << "var sbuf" << i << " : [[access(read)]] ReadOnlyStorageBuffer" + << i << ";\n"; - body += "if (sbuf" + std::to_string(i) + " != " + std::to_string(expectedValue++) + ") {\n"; - body += " return;\n"; - body += "}\n"; + body << "if (sbuf" << i << ".value != " << expectedValue++ << "u) {\n"; + body << " return;\n"; + body << "}\n"; } wgpu::Buffer result = utils::CreateBufferFromData( device, wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc, {0}); bgEntries.push_back({binding, result, 0, sizeof(uint32_t), nullptr, nullptr}); - interface += "layout(std430, set = 0, binding = " + std::to_string(binding++) + - ") writeonly buffer Result {\n"; - interface += " uint result;\n"; - interface += "};\n"; + interface << R"([[block]] struct ReadWriteStorageBuffer{ + [[offset(0)]] value : u32; + }; + )"; + interface << "[[set(0), binding(" << binding++ << ")]] " + << "var result : [[access(read_write)]] ReadWriteStorageBuffer;\n"; - body += "result = 1;\n"; - - std::string shader = interface + "void main() {\n" + body + "}\n"; + body << "result.value = 1u;\n"; + std::string shader = + interface.str() + "[[stage(compute)]] fn main() -> void {\n" + body.str() + "}\n"; wgpu::ComputePipelineDescriptor cpDesc; - cpDesc.computeStage.module = - utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, shader.c_str()); + cpDesc.computeStage.module = utils::CreateShaderModuleFromWGSL(device, shader.c_str()); cpDesc.computeStage.entryPoint = "main"; wgpu::ComputePipeline cp = device.CreateComputePipeline(&cpDesc);