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>
This commit is contained in:
parent
c4b4735a09
commit
b7eaedcfcc
@ -723,6 +723,8 @@ skia_dawn_sources = [
|
||||
"$_src/gpu/dawn/GrDawnProgramBuilder.h",
|
||||
"$_src/gpu/dawn/GrDawnRenderTarget.cpp",
|
||||
"$_src/gpu/dawn/GrDawnRenderTarget.h",
|
||||
"$_src/gpu/dawn/GrDawnRingBuffer.cpp",
|
||||
"$_src/gpu/dawn/GrDawnRingBuffer.h",
|
||||
"$_src/gpu/dawn/GrDawnStencilAttachment.cpp",
|
||||
"$_src/gpu/dawn/GrDawnStencilAttachment.h",
|
||||
"$_src/gpu/dawn/GrDawnTexture.cpp",
|
||||
|
@ -49,7 +49,8 @@ GrDawnGpu::GrDawnGpu(GrContext* context, const GrContextOptions& options,
|
||||
: INHERITED(context)
|
||||
, fDevice(device)
|
||||
, fQueue(device.CreateQueue())
|
||||
, fCompiler(new SkSL::Compiler()) {
|
||||
, fCompiler(new SkSL::Compiler())
|
||||
, fUniformRingBuffer(this, dawn::BufferUsageBit::Uniform) {
|
||||
fCaps.reset(new GrDawnCaps(options));
|
||||
}
|
||||
|
||||
@ -543,3 +544,7 @@ sk_sp<GrSemaphore> GrDawnGpu::prepareTextureForCrossContextUsage(GrTexture* text
|
||||
SkASSERT(!"unimplemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrDawnRingBuffer::Slice GrDawnGpu::allocateUniformRingBufferSlice(int size) {
|
||||
return fUniformRingBuffer.allocate(size);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "src/gpu/GrGpu.h"
|
||||
#include "dawn/dawncpp.h"
|
||||
#include "src/gpu/dawn/GrDawnRingBuffer.h"
|
||||
|
||||
class GrPipeline;
|
||||
class GrDawnGpuRTCommandBuffer;
|
||||
@ -82,6 +83,8 @@ public:
|
||||
|
||||
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
|
||||
|
||||
GrDawnRingBuffer::Slice allocateUniformRingBufferSlice(int size);
|
||||
|
||||
private:
|
||||
void onResetContext(uint32_t resetBits) override {}
|
||||
|
||||
@ -147,6 +150,7 @@ private:
|
||||
std::unique_ptr<SkSL::Compiler> fCompiler;
|
||||
std::unique_ptr<GrDawnGpuRTCommandBuffer> fRTCommandBuffer;
|
||||
std::unique_ptr<GrDawnGpuTextureCommandBuffer> fTextureCommandBuffer;
|
||||
GrDawnRingBuffer fUniformRingBuffer;
|
||||
|
||||
typedef GrGpu INHERITED;
|
||||
};
|
||||
|
@ -326,7 +326,8 @@ void GrDawnGpuRTCommandBuffer::applyState(const GrPipeline& pipeline,
|
||||
colorFormat, hasDepthStencil,
|
||||
stencilFormat, &desc);
|
||||
SkASSERT(program);
|
||||
program->setData(primProc, fRenderTarget, fOrigin, pipeline);
|
||||
auto bindGroup = program->setData(fGpu, fRenderTarget, fOrigin, primProc, pipeline,
|
||||
primProcProxies);
|
||||
|
||||
std::vector<dawn::VertexBufferDescriptor> inputs;
|
||||
std::vector<dawn::VertexAttributeDescriptor> vertexAttributes;
|
||||
@ -404,7 +405,7 @@ void GrDawnGpuRTCommandBuffer::applyState(const GrPipeline& pipeline,
|
||||
rpDesc.colorStates = colorStates;
|
||||
dawn::RenderPipeline renderPipeline = fGpu->device().CreateRenderPipeline(&rpDesc);
|
||||
fPassEncoder.SetPipeline(renderPipeline);
|
||||
fPassEncoder.SetBindGroup(0, program->fBindGroup, 0, nullptr);
|
||||
fPassEncoder.SetBindGroup(0, bindGroup, 0, nullptr);
|
||||
if (pipeline.isStencilEnabled()) {
|
||||
fPassEncoder.SetStencilReference(pipeline.getUserStencil()->fFront.fRef);
|
||||
}
|
||||
|
@ -347,54 +347,11 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
|
||||
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::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrig
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -60,8 +60,7 @@ struct GrDawnProgram : public SkRefCnt {
|
||||
std::unique_ptr<GrGLSLXferProcessor> fXferProcessor;
|
||||
std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors;
|
||||
int fFragmentProcessorCnt;
|
||||
dawn::Buffer fGeometryUniformBuffer;
|
||||
dawn::Buffer fFragmentUniformBuffer;
|
||||
dawn::BindGroupLayout fBindGroupLayout;
|
||||
dawn::PipelineLayout fPipelineLayout;
|
||||
dawn::BindGroup fBindGroup;
|
||||
dawn::ColorStateDescriptor fColorState;
|
||||
@ -71,8 +70,9 @@ struct GrDawnProgram : public SkRefCnt {
|
||||
BuiltinUniformHandles fBuiltinUniformHandles;
|
||||
|
||||
void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin);
|
||||
void setData(const GrPrimitiveProcessor&, const GrRenderTarget*, GrSurfaceOrigin,
|
||||
const GrPipeline&);
|
||||
dawn::BindGroup setData(GrDawnGpu* gpu, const GrRenderTarget*, GrSurfaceOrigin origin,
|
||||
const GrPrimitiveProcessor&, const GrPipeline&,
|
||||
const GrTextureProxy* const primProcTextures[]);
|
||||
};
|
||||
|
||||
class GrDawnProgramBuilder : public GrGLSLProgramBuilder {
|
||||
|
@ -263,16 +263,17 @@ template<> struct set_uniform_matrix<4> {
|
||||
}
|
||||
};
|
||||
|
||||
void GrDawnProgramDataManager::uploadUniformBuffers(dawn::Buffer geometryBuffer,
|
||||
dawn::Buffer fragmentBuffer) const {
|
||||
if (geometryBuffer && fGeometryUniformsDirty) {
|
||||
geometryBuffer.SetSubData(0, fGeometryUniformSize,
|
||||
static_cast<const uint8_t*>(fGeometryUniformData.get()));
|
||||
fGeometryUniformsDirty = false;
|
||||
void GrDawnProgramDataManager::uploadUniformBuffers(GrDawnRingBuffer::Slice geometryBuffer,
|
||||
GrDawnRingBuffer::Slice fragmentBuffer) const {
|
||||
|
||||
dawn::Buffer geom = geometryBuffer.fBuffer;
|
||||
dawn::Buffer frag = fragmentBuffer.fBuffer;
|
||||
if (geom && fGeometryUniformsDirty) {
|
||||
geom.SetSubData(geometryBuffer.fOffset, fGeometryUniformSize,
|
||||
static_cast<const uint8_t*>(fGeometryUniformData.get()));
|
||||
}
|
||||
if (fragmentBuffer && fFragmentUniformsDirty) {
|
||||
fragmentBuffer.SetSubData(0, fFragmentUniformSize,
|
||||
static_cast<const uint8_t*>(fFragmentUniformData.get()));
|
||||
fFragmentUniformsDirty = false;
|
||||
if (frag && fFragmentUniformsDirty) {
|
||||
frag.SetSubData(fragmentBuffer.fOffset, fFragmentUniformSize,
|
||||
static_cast<const uint8_t*>(fFragmentUniformData.get()));
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef GrDawnProgramDataManager_DEFINED
|
||||
#define GrDawnProgramDataManager_DEFINED
|
||||
|
||||
#include "src/gpu/dawn/GrDawnRingBuffer.h"
|
||||
#include "src/gpu/dawn/GrDawnUniformHandler.h"
|
||||
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
|
||||
#include "dawn/dawncpp.h"
|
||||
@ -57,8 +58,11 @@ public:
|
||||
SK_ABORT("Only supported in NVPR, which is not in Dawn");
|
||||
}
|
||||
|
||||
void uploadUniformBuffers(dawn::Buffer geometryBuffer, dawn::Buffer fragmentBuffer) const;
|
||||
void uploadUniformBuffers(GrDawnRingBuffer::Slice geometryBuffer,
|
||||
GrDawnRingBuffer::Slice fragmentBuffer) const;
|
||||
|
||||
uint32_t geometryUniformSize() const { return fGeometryUniformSize; }
|
||||
uint32_t fragmentUniformSize() const { return fFragmentUniformSize; }
|
||||
private:
|
||||
struct Uniform {
|
||||
uint32_t fBinding;
|
||||
|
36
src/gpu/dawn/GrDawnRingBuffer.cpp
Normal file
36
src/gpu/dawn/GrDawnRingBuffer.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/dawn/GrDawnRingBuffer.h"
|
||||
|
||||
#include "src/gpu/dawn/GrDawnGpu.h"
|
||||
#include "src/gpu/dawn/GrDawnUtil.h"
|
||||
|
||||
namespace {
|
||||
const int kDefaultSize = 512 * 1024;
|
||||
}
|
||||
|
||||
GrDawnRingBuffer::GrDawnRingBuffer(GrDawnGpu* gpu, dawn::BufferUsageBit usage)
|
||||
: fGpu(gpu) , fUsage(usage) {
|
||||
}
|
||||
|
||||
GrDawnRingBuffer::~GrDawnRingBuffer() {
|
||||
}
|
||||
|
||||
GrDawnRingBuffer::Slice GrDawnRingBuffer::allocate(int size) {
|
||||
if (!fBuffer || fOffset + size > kDefaultSize) {
|
||||
dawn::BufferDescriptor desc;
|
||||
desc.usage = fUsage | dawn::BufferUsageBit::CopyDst;
|
||||
desc.size = kDefaultSize;
|
||||
fBuffer = fGpu->device().CreateBuffer(&desc);
|
||||
fOffset = 0;
|
||||
}
|
||||
int offset = fOffset;
|
||||
fOffset += size;
|
||||
fOffset = GrDawnRoundRowBytes(fOffset);
|
||||
return Slice(fBuffer, offset);
|
||||
}
|
43
src/gpu/dawn/GrDawnRingBuffer.h
Normal file
43
src/gpu/dawn/GrDawnRingBuffer.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrDawnRingBuffer_DEFINED
|
||||
#define GrDawnRingBuffer_DEFINED
|
||||
|
||||
#include "src/gpu/GrBuffer.h"
|
||||
#include "src/gpu/dawn/GrDawnBuffer.h"
|
||||
#include "dawn/dawncpp.h"
|
||||
|
||||
class GrDawnGpu;
|
||||
|
||||
class GrDawnRingBuffer : public SkRefCnt {
|
||||
public:
|
||||
GrDawnRingBuffer(GrDawnGpu* gpu, dawn::BufferUsageBit usage);
|
||||
~GrDawnRingBuffer() override;
|
||||
|
||||
struct Slice {
|
||||
Slice(dawn::Buffer buffer, int offset) : fBuffer(buffer), fOffset(offset) {}
|
||||
Slice() : fBuffer(nullptr), fOffset(0) {}
|
||||
Slice(const Slice& other) : fBuffer(other.fBuffer), fOffset(other.fOffset) {}
|
||||
Slice& operator=(const Slice& other) {
|
||||
fBuffer = other.fBuffer;
|
||||
fOffset = other.fOffset;
|
||||
return *this;
|
||||
}
|
||||
dawn::Buffer fBuffer;
|
||||
int fOffset;
|
||||
};
|
||||
Slice allocate(int size);
|
||||
|
||||
private:
|
||||
GrDawnGpu* fGpu;
|
||||
dawn::BufferUsageBit fUsage;
|
||||
dawn::Buffer fBuffer;
|
||||
int fOffset = 0;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user