Support setting bind groups before pipeline for all backends

This is to match WebGPU semantics.

Bug: dawn:201
Change-Id: I2aab671fc389edf1d2765395814a9c831afc653e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11080
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Austin Eng
2019-09-17 19:25:27 +00:00
committed by Commit Bot service account
parent 617e356580
commit 7f3f331ce6
7 changed files with 352 additions and 330 deletions

View File

@@ -15,6 +15,7 @@
#include "dawn_native/opengl/CommandBufferGL.h"
#include "dawn_native/BindGroup.h"
#include "dawn_native/BindGroupTracker.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/RenderBundle.h"
@@ -215,88 +216,109 @@ namespace dawn_native { namespace opengl {
RenderPipelineBase* mLastPipeline = nullptr;
};
// Handles SetBindGroup commands with the specifics of translating to OpenGL texture and
// buffer units
void ApplyBindGroup(const OpenGLFunctions& gl,
uint32_t index,
BindGroupBase* group,
PipelineLayout* pipelineLayout,
PipelineGL* pipeline,
uint32_t dynamicOffsetCount,
uint64_t* dynamicOffsets) {
const auto& indices = pipelineLayout->GetBindingIndexInfo()[index];
const auto& layout = group->GetLayout()->GetBindingInfo();
uint32_t currentDynamicIndex = 0;
class BindGroupTracker : public BindGroupTrackerBase<BindGroupBase*, false> {
public:
void OnSetPipeline(RenderPipeline* pipeline) {
BindGroupTrackerBase::OnSetPipeline(pipeline);
mPipeline = pipeline;
}
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
switch (layout.types[bindingIndex]) {
case dawn::BindingType::UniformBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint uboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
void OnSetPipeline(ComputePipeline* pipeline) {
BindGroupTrackerBase::OnSetPipeline(pipeline);
mPipeline = pipeline;
}
if (layout.dynamic[bindingIndex]) {
offset += dynamicOffsets[currentDynamicIndex];
++currentDynamicIndex;
}
void Apply(const OpenGLFunctions& gl) {
for (uint32_t index : IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) {
ApplyBindGroup(gl, index, mBindGroups[index], mDynamicOffsetCounts[index],
mDynamicOffsets[index].data());
}
DidApply();
}
gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, offset,
binding.size);
} break;
private:
void ApplyBindGroup(const OpenGLFunctions& gl,
uint32_t index,
BindGroupBase* group,
uint32_t dynamicOffsetCount,
uint64_t* dynamicOffsets) {
const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index];
const auto& layout = group->GetLayout()->GetBindingInfo();
uint32_t currentDynamicIndex = 0;
case dawn::BindingType::Sampler: {
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
GLuint samplerIndex = indices[bindingIndex];
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
switch (layout.types[bindingIndex]) {
case dawn::BindingType::UniformBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint uboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
for (PipelineGL::SamplerUnit unit :
pipeline->GetTextureUnitsForSampler(samplerIndex)) {
// Only use filtering for certain texture units, because int and uint
// texture are only complete without filtering
if (unit.shouldUseFiltering) {
gl.BindSampler(unit.unit, sampler->GetFilteringHandle());
} else {
gl.BindSampler(unit.unit, sampler->GetNonFilteringHandle());
if (layout.dynamic[bindingIndex]) {
offset += dynamicOffsets[currentDynamicIndex];
++currentDynamicIndex;
}
}
} break;
case dawn::BindingType::SampledTexture: {
TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex));
GLuint handle = view->GetHandle();
GLenum target = view->GetGLTarget();
GLuint viewIndex = indices[bindingIndex];
gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, offset,
binding.size);
} break;
for (auto unit : pipeline->GetTextureUnitsForTextureView(viewIndex)) {
gl.ActiveTexture(GL_TEXTURE0 + unit);
gl.BindTexture(target, handle);
}
} break;
case dawn::BindingType::Sampler: {
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
GLuint samplerIndex = indices[bindingIndex];
case dawn::BindingType::StorageBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint ssboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
for (PipelineGL::SamplerUnit unit :
mPipeline->GetTextureUnitsForSampler(samplerIndex)) {
// Only use filtering for certain texture units, because int and
// uint texture are only complete without filtering
if (unit.shouldUseFiltering) {
gl.BindSampler(unit.unit, sampler->GetFilteringHandle());
} else {
gl.BindSampler(unit.unit, sampler->GetNonFilteringHandle());
}
}
} break;
if (layout.dynamic[bindingIndex]) {
offset += dynamicOffsets[currentDynamicIndex];
++currentDynamicIndex;
}
case dawn::BindingType::SampledTexture: {
TextureView* view =
ToBackend(group->GetBindingAsTextureView(bindingIndex));
GLuint handle = view->GetHandle();
GLenum target = view->GetGLTarget();
GLuint viewIndex = indices[bindingIndex];
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
binding.size);
} break;
for (auto unit : mPipeline->GetTextureUnitsForTextureView(viewIndex)) {
gl.ActiveTexture(GL_TEXTURE0 + unit);
gl.BindTexture(target, handle);
}
} break;
case dawn::BindingType::StorageTexture:
case dawn::BindingType::ReadonlyStorageBuffer:
UNREACHABLE();
break;
case dawn::BindingType::StorageBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint ssboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
if (layout.dynamic[bindingIndex]) {
offset += dynamicOffsets[currentDynamicIndex];
++currentDynamicIndex;
}
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
binding.size);
} break;
case dawn::BindingType::StorageTexture:
case dawn::BindingType::ReadonlyStorageBuffer:
UNREACHABLE();
break;
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
}
}
}
}
PipelineGL* mPipeline = nullptr;
};
void ResolveMultisampledRenderTargets(const OpenGLFunctions& gl,
const BeginRenderPassCmd* renderPass) {
@@ -608,6 +630,7 @@ namespace dawn_native { namespace opengl {
void CommandBuffer::ExecuteComputePass() {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
ComputePipeline* lastPipeline = nullptr;
BindGroupTracker bindGroupTracker = {};
Command type;
while (mCommands.NextCommandId(&type)) {
@@ -619,6 +642,8 @@ namespace dawn_native { namespace opengl {
case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
bindGroupTracker.Apply(gl);
gl.DispatchCompute(dispatch->x, dispatch->y, dispatch->z);
// TODO(cwallez@chromium.org): add barriers to the API
gl.MemoryBarrier(GL_ALL_BARRIER_BITS);
@@ -626,6 +651,7 @@ namespace dawn_native { namespace opengl {
case Command::DispatchIndirect: {
DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();
bindGroupTracker.Apply(gl);
uint64_t indirectBufferOffset = dispatch->indirectOffset;
Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get());
@@ -640,6 +666,8 @@ namespace dawn_native { namespace opengl {
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow();
bindGroupTracker.OnSetPipeline(lastPipeline);
} break;
case Command::SetBindGroup: {
@@ -648,9 +676,8 @@ namespace dawn_native { namespace opengl {
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
}
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
ToBackend(lastPipeline->GetLayout()), lastPipeline,
cmd->dynamicOffsetCount, dynamicOffsets);
bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
cmd->dynamicOffsetCount, dynamicOffsets);
} break;
case Command::InsertDebugMarker:
@@ -802,12 +829,14 @@ namespace dawn_native { namespace opengl {
uint64_t indexBufferBaseOffset = 0;
InputBufferTracker inputBuffers;
BindGroupTracker bindGroupTracker = {};
auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>();
inputBuffers.Apply(gl);
bindGroupTracker.Apply(gl);
if (draw->firstInstance > 0) {
gl.DrawArraysInstancedBaseInstance(
@@ -824,6 +853,7 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
inputBuffers.Apply(gl);
bindGroupTracker.Apply(gl);
dawn::IndexFormat indexFormat =
lastPipeline->GetVertexInputDescriptor()->indexFormat;
@@ -849,6 +879,7 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
inputBuffers.Apply(gl);
bindGroupTracker.Apply(gl);
uint64_t indirectBufferOffset = draw->indirectOffset;
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
@@ -862,6 +893,7 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
inputBuffers.Apply(gl);
bindGroupTracker.Apply(gl);
dawn::IndexFormat indexFormat =
lastPipeline->GetVertexInputDescriptor()->indexFormat;
@@ -890,6 +922,7 @@ namespace dawn_native { namespace opengl {
lastPipeline->ApplyNow(persistentPipelineState);
inputBuffers.OnSetPipeline(lastPipeline);
bindGroupTracker.OnSetPipeline(lastPipeline);
} break;
case Command::SetBindGroup: {
@@ -898,9 +931,8 @@ namespace dawn_native { namespace opengl {
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
ToBackend(lastPipeline->GetLayout()), lastPipeline,
cmd->dynamicOffsetCount, dynamicOffsets);
bindGroupTracker.OnSetBindGroup(cmd->index, cmd->group.Get(),
cmd->dynamicOffsetCount, dynamicOffsets);
} break;
case Command::SetIndexBuffer: {