diff --git a/gn/gpu.gni b/gn/gpu.gni index bb4210d776..84fd169cb3 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -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", diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp index 1fd124f14e..f21cbb9869 100644 --- a/src/gpu/dawn/GrDawnGpu.cpp +++ b/src/gpu/dawn/GrDawnGpu.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 GrDawnGpu::prepareTextureForCrossContextUsage(GrTexture* text SkASSERT(!"unimplemented"); return nullptr; } + +GrDawnRingBuffer::Slice GrDawnGpu::allocateUniformRingBufferSlice(int size) { + return fUniformRingBuffer.allocate(size); +} diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h index 39730553a4..736e6cc89b 100644 --- a/src/gpu/dawn/GrDawnGpu.h +++ b/src/gpu/dawn/GrDawnGpu.h @@ -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 prepareTextureForCrossContextUsage(GrTexture*) override; + GrDawnRingBuffer::Slice allocateUniformRingBufferSlice(int size); + private: void onResetContext(uint32_t resetBits) override {} @@ -147,6 +150,7 @@ private: std::unique_ptr fCompiler; std::unique_ptr fRTCommandBuffer; std::unique_ptr fTextureCommandBuffer; + GrDawnRingBuffer fUniformRingBuffer; typedef GrGpu INHERITED; }; diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp index 020207e19e..312663d139 100644 --- a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp +++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp @@ -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 inputs; std::vector 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); } diff --git a/src/gpu/dawn/GrDawnProgramBuilder.cpp b/src/gpu/dawn/GrDawnProgramBuilder.cpp index f0fe75979b..db51fceaf7 100644 --- a/src/gpu/dawn/GrDawnProgramBuilder.cpp +++ b/src/gpu/dawn/GrDawnProgramBuilder.cpp @@ -347,54 +347,11 @@ sk_sp 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(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(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 *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(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 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); } diff --git a/src/gpu/dawn/GrDawnProgramBuilder.h b/src/gpu/dawn/GrDawnProgramBuilder.h index 319dff9712..a98f27074a 100644 --- a/src/gpu/dawn/GrDawnProgramBuilder.h +++ b/src/gpu/dawn/GrDawnProgramBuilder.h @@ -60,8 +60,7 @@ struct GrDawnProgram : public SkRefCnt { std::unique_ptr fXferProcessor; std::unique_ptr[]> 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 { diff --git a/src/gpu/dawn/GrDawnProgramDataManager.cpp b/src/gpu/dawn/GrDawnProgramDataManager.cpp index 45371f4e81..b2bb013f71 100644 --- a/src/gpu/dawn/GrDawnProgramDataManager.cpp +++ b/src/gpu/dawn/GrDawnProgramDataManager.cpp @@ -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(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(fGeometryUniformData.get())); } - if (fragmentBuffer && fFragmentUniformsDirty) { - fragmentBuffer.SetSubData(0, fFragmentUniformSize, - static_cast(fFragmentUniformData.get())); - fFragmentUniformsDirty = false; + if (frag && fFragmentUniformsDirty) { + frag.SetSubData(fragmentBuffer.fOffset, fFragmentUniformSize, + static_cast(fFragmentUniformData.get())); } } diff --git a/src/gpu/dawn/GrDawnProgramDataManager.h b/src/gpu/dawn/GrDawnProgramDataManager.h index 0b2f35e8fb..d74f1ee7f7 100644 --- a/src/gpu/dawn/GrDawnProgramDataManager.h +++ b/src/gpu/dawn/GrDawnProgramDataManager.h @@ -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; diff --git a/src/gpu/dawn/GrDawnRingBuffer.cpp b/src/gpu/dawn/GrDawnRingBuffer.cpp new file mode 100644 index 0000000000..0e26369726 --- /dev/null +++ b/src/gpu/dawn/GrDawnRingBuffer.cpp @@ -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); +} diff --git a/src/gpu/dawn/GrDawnRingBuffer.h b/src/gpu/dawn/GrDawnRingBuffer.h new file mode 100644 index 0000000000..48e2576fda --- /dev/null +++ b/src/gpu/dawn/GrDawnRingBuffer.h @@ -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