diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp index 90cdb06021..4abff6e098 100644 --- a/src/dawn_native/BindGroupLayout.cpp +++ b/src/dawn_native/BindGroupLayout.cpp @@ -42,6 +42,10 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("some binding index was specified more than once"); } + if (binding.visibility == dawn::ShaderStageBit::None) { + return DAWN_VALIDATION_ERROR("Visibility of bindings can't be None"); + } + switch (binding.type) { case dawn::BindingType::UniformBuffer: case dawn::BindingType::StorageBuffer: diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index c520a3f3a1..d7a07bc515 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -220,9 +220,12 @@ namespace dawn_native { namespace opengl { uint32_t index, BindGroupBase* group, PipelineLayout* pipelineLayout, - PipelineGL* pipeline) { + PipelineGL* pipeline, + uint32_t dynamicOffsetCount, + uint64_t* dynamicOffsets) { const auto& indices = pipelineLayout->GetBindingIndexInfo()[index]; const auto& layout = group->GetLayout()->GetBindingInfo(); + uint32_t currentDynamicIndex = 0; for (uint32_t bindingIndex : IterateBitSet(layout.mask)) { switch (layout.types[bindingIndex]) { @@ -230,8 +233,14 @@ namespace dawn_native { namespace opengl { BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex); GLuint buffer = ToBackend(binding.buffer)->GetHandle(); GLuint uboIndex = indices[bindingIndex]; + GLuint offset = binding.offset; - gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, binding.offset, + if (layout.dynamic[bindingIndex]) { + offset += dynamicOffsets[currentDynamicIndex]; + ++currentDynamicIndex; + } + + gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, offset, binding.size); } break; @@ -261,9 +270,15 @@ namespace dawn_native { namespace opengl { BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex); GLuint buffer = ToBackend(binding.buffer)->GetHandle(); GLuint ssboIndex = indices[bindingIndex]; + GLuint offset = binding.offset; - gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, - binding.offset, binding.size); + if (layout.dynamic[bindingIndex]) { + offset += dynamicOffsets[currentDynamicIndex]; + ++currentDynamicIndex; + } + + gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset, + binding.size); } break; case dawn::BindingType::StorageTexture: @@ -555,8 +570,13 @@ namespace dawn_native { namespace opengl { case Command::SetBindGroup: { SetBindGroupCmd* cmd = mCommands.NextCommand(); + uint64_t* dynamicOffsets = nullptr; + if (cmd->dynamicOffsetCount > 0) { + dynamicOffsets = mCommands.NextData(cmd->dynamicOffsetCount); + } ApplyBindGroup(gl, cmd->index, cmd->group.Get(), - ToBackend(lastPipeline->GetLayout()), lastPipeline); + ToBackend(lastPipeline->GetLayout()), lastPipeline, + cmd->dynamicOffsetCount, dynamicOffsets); } break; default: { UNREACHABLE(); } break; @@ -830,8 +850,13 @@ namespace dawn_native { namespace opengl { case Command::SetBindGroup: { SetBindGroupCmd* cmd = mCommands.NextCommand(); + uint64_t* dynamicOffsets = nullptr; + if (cmd->dynamicOffsetCount > 0) { + dynamicOffsets = mCommands.NextData(cmd->dynamicOffsetCount); + } ApplyBindGroup(gl, cmd->index, cmd->group.Get(), - ToBackend(lastPipeline->GetLayout()), lastPipeline); + ToBackend(lastPipeline->GetLayout()), lastPipeline, + cmd->dynamicOffsetCount, dynamicOffsets); } break; case Command::SetIndexBuffer: { diff --git a/src/tests/end2end/DynamicBufferOffsetTests.cpp b/src/tests/end2end/DynamicBufferOffsetTests.cpp index 0a25fd0f89..1af54ae0fb 100644 --- a/src/tests/end2end/DynamicBufferOffsetTests.cpp +++ b/src/tests/end2end/DynamicBufferOffsetTests.cpp @@ -212,4 +212,4 @@ TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsComputePipeline) { kMinDynamicBufferOffsetAlignment, expectedData.size()); } -DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests, MetalBackend, VulkanBackend); +DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests, MetalBackend, OpenGLBackend, VulkanBackend); diff --git a/src/tests/unittests/validation/BindGroupValidationTests.cpp b/src/tests/unittests/validation/BindGroupValidationTests.cpp index 016dc0bf7e..7bf8b0a6bf 100644 --- a/src/tests/unittests/validation/BindGroupValidationTests.cpp +++ b/src/tests/unittests/validation/BindGroupValidationTests.cpp @@ -472,6 +472,21 @@ TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutCache) { ASSERT_EQ(layout1.Get(), layout2.Get()); } +// This test verifies that visibility of bindings in BindGroupLayout can't be none +TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutVisibilityNone) { + utils::MakeBindGroupLayout( + device, { + {0, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}, + }); + + dawn::BindGroupLayoutBinding binding = {0, dawn::ShaderStageBit::None, + dawn::BindingType::UniformBuffer}; + dawn::BindGroupLayoutDescriptor descriptor; + descriptor.bindingCount = 1; + descriptor.bindings = &binding; + ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&descriptor)); +} + constexpr uint64_t kBufferSize = 2 * kMinDynamicBufferOffsetAlignment + 8; constexpr uint32_t kBindingSize = 9;