Dawn: implement a ring buffer for uniform uploads.
GrDawnGpu vends ring buffer slices out of a persistent (larger) buffer.
GrDawnProgramDataManager::setData() now returns a BindGroup containing
the (possibly new) UBO bindings, as well as the texture and sampler
bindings.
Change-Id: Id6694d6f44a815cfbffe4293779bf9bf558a2365
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235866
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/gpu/dawn/GrDawnProgramBuilder.cpp b/src/gpu/dawn/GrDawnProgramBuilder.cpp
index f0fe759..db51fce 100644
--- a/src/gpu/dawn/GrDawnProgramBuilder.cpp
+++ b/src/gpu/dawn/GrDawnProgramBuilder.cpp
@@ -347,54 +347,11 @@
dawn::BindGroupLayoutDescriptor bindGroupLayoutDesc;
bindGroupLayoutDesc.bindingCount = layoutBindings.size();
bindGroupLayoutDesc.bindings = layoutBindings.data();
- auto bindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc);
+ result->fBindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc);
dawn::PipelineLayoutDescriptor pipelineLayoutDesc;
pipelineLayoutDesc.bindGroupLayoutCount = 1;
- pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
+ pipelineLayoutDesc.bindGroupLayouts = &result->fBindGroupLayout;
result->fPipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
- if (0 != geometryUniformSize) {
- dawn::BufferDescriptor desc;
- desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
- desc.size = geometryUniformSize;
- result->fGeometryUniformBuffer = gpu->device().CreateBuffer(&desc);
- bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kGeometryBinding,
- result->fGeometryUniformBuffer,
- 0, geometryUniformSize));
- }
- if (0 != fragmentUniformSize) {
- dawn::BufferDescriptor desc;
- desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
- desc.size = fragmentUniformSize;
- result->fFragmentUniformBuffer = gpu->device().CreateBuffer(&desc);
- bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kFragBinding,
- result->fFragmentUniformBuffer,
- 0, fragmentUniformSize));
- }
- binding = GrDawnUniformHandler::kSamplerBindingBase;
- for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
- dawn::Sampler sampler = create_sampler(gpu, primProc.textureSampler(i).samplerState());
- bindings.push_back(make_bind_group_binding(binding++, sampler));
- GrDawnTexture* tex = static_cast<GrDawnTexture*>(primProcProxies[i]->peekTexture());
- dawn::TextureView textureView = tex->textureView();
- bindings.push_back(make_bind_group_binding(binding++, textureView));
- }
- GrFragmentProcessor::Iter iter(pipeline);
- const GrFragmentProcessor* fp = iter.next();
- while (fp) {
- for (int i = 0; i < fp->numTextureSamplers(); ++i) {
- dawn::Sampler sampler = create_sampler(gpu, fp->textureSampler(i).samplerState());
- bindings.push_back(make_bind_group_binding(binding++, sampler));
- GrDawnTexture* tex = static_cast<GrDawnTexture*>(fp->textureSampler(i).peekTexture());
- dawn::TextureView textureView = tex->textureView();
- bindings.push_back(make_bind_group_binding(binding++, textureView));
- }
- fp = iter.next();
- }
- dawn::BindGroupDescriptor bindGroupDescriptor;
- bindGroupDescriptor.layout = bindGroupLayout;
- bindGroupDescriptor.bindingCount = bindings.size();
- bindGroupDescriptor.bindings = bindings.data();
- result->fBindGroup = gpu->device().CreateBindGroup(&bindGroupDescriptor);
result->fBuiltinUniformHandles = builder.fUniformHandles;
result->fColorState = create_color_state(gpu, pipeline, colorFormat);
GrStencilSettings stencil;
@@ -465,22 +422,70 @@
}
}
-void GrDawnProgram::setData(const GrPrimitiveProcessor& primProc,
- const GrRenderTarget* renderTarget,
- GrSurfaceOrigin origin,
- const GrPipeline& pipeline) {
+static void setTexture(GrDawnGpu* gpu, const GrSamplerState& state, GrTexture* texture,
+ std::vector<dawn::BindGroupBinding> *bindings, int* binding) {
+ // FIXME: could probably cache samplers in GrDawnProgram
+ dawn::Sampler sampler = create_sampler(gpu, state);
+ bindings->push_back(make_bind_group_binding((*binding)++, sampler));
+ GrDawnTexture* tex = static_cast<GrDawnTexture*>(texture);
+ dawn::TextureView textureView = tex->textureView();
+ bindings->push_back(make_bind_group_binding((*binding)++, textureView));
+}
+
+dawn::BindGroup GrDawnProgram::setData(GrDawnGpu* gpu, const GrRenderTarget* renderTarget,
+ GrSurfaceOrigin origin,
+ const GrPrimitiveProcessor& primProc,
+ const GrPipeline& pipeline,
+ const GrTextureProxy* const primProcTextures[]) {
+ std::vector<dawn::BindGroupBinding> bindings;
+ GrDawnRingBuffer::Slice geom, frag;
+ uint32_t geometryUniformSize = fDataManager.geometryUniformSize();
+ uint32_t fragmentUniformSize = fDataManager.fragmentUniformSize();
+ if (0 != geometryUniformSize) {
+ geom = gpu->allocateUniformRingBufferSlice(geometryUniformSize);
+ bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kGeometryBinding,
+ geom.fBuffer, geom.fOffset,
+ geometryUniformSize));
+ }
+ if (0 != fragmentUniformSize) {
+ frag = gpu->allocateUniformRingBufferSlice(fragmentUniformSize);
+ bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kFragBinding,
+ frag.fBuffer, frag.fOffset,
+ fragmentUniformSize));
+ }
this->setRenderTargetState(renderTarget, origin);
fGeometryProcessor->setData(fDataManager, primProc,
GrFragmentProcessor::CoordTransformIter(pipeline));
+ int binding = GrDawnUniformHandler::kSamplerBindingBase;
+ for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
+ auto& sampler = primProc.textureSampler(i);
+ setTexture(gpu, sampler.samplerState(), primProcTextures[i]->peekTexture(), &bindings,
+ &binding);
+ }
GrFragmentProcessor::Iter iter(pipeline);
GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
const GrFragmentProcessor* fp = iter.next();
GrGLSLFragmentProcessor* glslFP = glslIter.next();
while (fp && glslFP) {
glslFP->setData(fDataManager, *fp);
+ for (int i = 0; i < fp->numTextureSamplers(); ++i) {
+ auto& s = fp->textureSampler(i);
+ setTexture(gpu, s.samplerState(), s.peekTexture(), &bindings, &binding);
+ }
fp = iter.next();
glslFP = glslIter.next();
}
- fDataManager.uploadUniformBuffers(fGeometryUniformBuffer,
- fFragmentUniformBuffer);
+ SkIPoint offset;
+ GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
+ fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
+ if (GrTextureProxy* proxy = pipeline.dstTextureProxy()) {
+ GrFragmentProcessor::TextureSampler sampler(sk_ref_sp(proxy));
+ setTexture(gpu, sampler.samplerState(), sampler.peekTexture(), &bindings, &binding);
+ }
+ fDataManager.uploadUniformBuffers(geom, frag);
+ dawn::BindGroupDescriptor descriptor;
+ descriptor.layout = fBindGroupLayout;
+ descriptor.bindingCount = bindings.size();
+ descriptor.bindings = bindings.data();
+ return gpu->device().CreateBindGroup(&descriptor);
}