Dynamic Buffer Offset : OpenGL Backend
In a typical graphics application it is a common usage to update some uniforms once per draw, and such uniforms include the word positions, orientations, and so on. In the current state of WebGPU, this means that for each draw call we have to create a new bind group to set the right uniform values. Bind group creation is expected to be more expensive than recording draws because a memory allocation is required. The functionality of dynamic buffer offset is to reduce the number of bind groups that need to be created. The patch implements dynamic buffer offset on OpenGL backend using glBindBufferRange and adds validation to check whether visibility of resources are none. Bug=dawn:55 Change-Id: I77e10a9677d1737f377301ee89e29d904c91c298 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9540 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
This commit is contained in:
parent
7dec2d1c56
commit
34f8bd8c48
|
@ -42,6 +42,10 @@ namespace dawn_native {
|
||||||
return DAWN_VALIDATION_ERROR("some binding index was specified more than once");
|
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) {
|
switch (binding.type) {
|
||||||
case dawn::BindingType::UniformBuffer:
|
case dawn::BindingType::UniformBuffer:
|
||||||
case dawn::BindingType::StorageBuffer:
|
case dawn::BindingType::StorageBuffer:
|
||||||
|
|
|
@ -220,9 +220,12 @@ namespace dawn_native { namespace opengl {
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
BindGroupBase* group,
|
BindGroupBase* group,
|
||||||
PipelineLayout* pipelineLayout,
|
PipelineLayout* pipelineLayout,
|
||||||
PipelineGL* pipeline) {
|
PipelineGL* pipeline,
|
||||||
|
uint32_t dynamicOffsetCount,
|
||||||
|
uint64_t* dynamicOffsets) {
|
||||||
const auto& indices = pipelineLayout->GetBindingIndexInfo()[index];
|
const auto& indices = pipelineLayout->GetBindingIndexInfo()[index];
|
||||||
const auto& layout = group->GetLayout()->GetBindingInfo();
|
const auto& layout = group->GetLayout()->GetBindingInfo();
|
||||||
|
uint32_t currentDynamicIndex = 0;
|
||||||
|
|
||||||
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
|
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
|
||||||
switch (layout.types[bindingIndex]) {
|
switch (layout.types[bindingIndex]) {
|
||||||
|
@ -230,8 +233,14 @@ namespace dawn_native { namespace opengl {
|
||||||
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
|
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
|
||||||
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
|
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
|
||||||
GLuint uboIndex = indices[bindingIndex];
|
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);
|
binding.size);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -261,9 +270,15 @@ namespace dawn_native { namespace opengl {
|
||||||
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
|
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
|
||||||
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
|
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
|
||||||
GLuint ssboIndex = indices[bindingIndex];
|
GLuint ssboIndex = indices[bindingIndex];
|
||||||
|
GLuint offset = binding.offset;
|
||||||
|
|
||||||
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer,
|
if (layout.dynamic[bindingIndex]) {
|
||||||
binding.offset, binding.size);
|
offset += dynamicOffsets[currentDynamicIndex];
|
||||||
|
++currentDynamicIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
|
||||||
|
binding.size);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dawn::BindingType::StorageTexture:
|
case dawn::BindingType::StorageTexture:
|
||||||
|
@ -555,8 +570,13 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
case Command::SetBindGroup: {
|
case Command::SetBindGroup: {
|
||||||
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
||||||
|
uint64_t* dynamicOffsets = nullptr;
|
||||||
|
if (cmd->dynamicOffsetCount > 0) {
|
||||||
|
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
|
||||||
|
}
|
||||||
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
|
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
|
||||||
ToBackend(lastPipeline->GetLayout()), lastPipeline);
|
ToBackend(lastPipeline->GetLayout()), lastPipeline,
|
||||||
|
cmd->dynamicOffsetCount, dynamicOffsets);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: { UNREACHABLE(); } break;
|
default: { UNREACHABLE(); } break;
|
||||||
|
@ -830,8 +850,13 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
case Command::SetBindGroup: {
|
case Command::SetBindGroup: {
|
||||||
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
||||||
|
uint64_t* dynamicOffsets = nullptr;
|
||||||
|
if (cmd->dynamicOffsetCount > 0) {
|
||||||
|
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
|
||||||
|
}
|
||||||
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
|
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
|
||||||
ToBackend(lastPipeline->GetLayout()), lastPipeline);
|
ToBackend(lastPipeline->GetLayout()), lastPipeline,
|
||||||
|
cmd->dynamicOffsetCount, dynamicOffsets);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Command::SetIndexBuffer: {
|
case Command::SetIndexBuffer: {
|
||||||
|
|
|
@ -212,4 +212,4 @@ TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsComputePipeline) {
|
||||||
kMinDynamicBufferOffsetAlignment, expectedData.size());
|
kMinDynamicBufferOffsetAlignment, expectedData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests, MetalBackend, VulkanBackend);
|
DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests, MetalBackend, OpenGLBackend, VulkanBackend);
|
||||||
|
|
|
@ -472,6 +472,21 @@ TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutCache) {
|
||||||
ASSERT_EQ(layout1.Get(), layout2.Get());
|
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 uint64_t kBufferSize = 2 * kMinDynamicBufferOffsetAlignment + 8;
|
||||||
constexpr uint32_t kBindingSize = 9;
|
constexpr uint32_t kBindingSize = 9;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue