diff --git a/src/gpu/dawn/GrDawnCaps.cpp b/src/gpu/dawn/GrDawnCaps.cpp index 490b5aa24e..106068baa0 100644 --- a/src/gpu/dawn/GrDawnCaps.cpp +++ b/src/gpu/dawn/GrDawnCaps.cpp @@ -8,12 +8,22 @@ #include "src/gpu/dawn/GrDawnCaps.h" GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) { + fMipMapSupport = true; fBufferMapThreshold = SK_MaxS32; // FIXME: get this from Dawn? fShaderCaps.reset(new GrShaderCaps(contextOptions)); - fMaxTextureSize = 2048; // FIXME + fMaxTextureSize = fMaxRenderTargetSize = 4096; // FIXME fMaxVertexAttributes = 16; // FIXME + fClampToBorderSupport = false; fPerformPartialClearsAsDraws = true; + fShaderCaps->fFlatInterpolationSupport = true; + fShaderCaps->fIntegerSupport = true; + // FIXME: each fragment sampler takes two binding slots in Dawn (sampler + texture). Limit to + // 6 * 2 = 12, since kMaxBindingsPerGroup is 16 in Dawn, and we need to keep a few for + // non-texture bindings. Eventually, we may be able to increase kMaxBindingsPerGroup in Dawn. + fShaderCaps->fMaxFragmentSamplers = 6; + fShaderCaps->fShaderDerivativeSupport = true; + this->applyOptionsOverrides(contextOptions); fShaderCaps->applyOptionsOverrides(contextOptions); } diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp index 2f7f9fb4e1..5e09f15b6a 100644 --- a/src/gpu/dawn/GrDawnGpu.cpp +++ b/src/gpu/dawn/GrDawnGpu.cpp @@ -23,7 +23,10 @@ #include "src/gpu/dawn/GrDawnRenderTarget.h" #include "src/gpu/dawn/GrDawnStencilAttachment.h" #include "src/gpu/dawn/GrDawnTexture.h" +#include "src/gpu/dawn/GrDawnUtil.h" +#include "src/core/SkAutoMalloc.h" +#include "src/core/SkMipMap.h" #include "src/sksl/SkSLCompiler.h" #if !defined(SK_BUILD_FOR_WIN) @@ -222,15 +225,102 @@ GrStencilAttachment* GrDawnGpu::createStencilAttachmentForRenderTarget(const GrR } GrBackendTexture GrDawnGpu::createBackendTexture(int width, int height, - const GrBackendFormat& format, + const GrBackendFormat& backendFormat, GrMipMapped mipMapped, GrRenderable renderable, const void* pixels, size_t rowBytes, const SkColor4f* color, GrProtected isProtected) { - SkASSERT(!"unimplemented"); - return GrBackendTexture(); + dawn::TextureFormat format; + if (!backendFormat.asDawnFormat(&format)) { + return GrBackendTexture(); + } + + GrPixelConfig config = GrDawnFormatToPixelConfig(format); + + if (width > this->caps()->maxTextureSize() || height > this->caps()->maxTextureSize()) { + return GrBackendTexture(); + } + + // Currently we don't support uploading pixel data when mipped. + if (pixels && GrMipMapped::kYes == mipMapped) { + return GrBackendTexture(); + } + + dawn::TextureDescriptor desc; + desc.usage = + dawn::TextureUsageBit::Sampled | + dawn::TextureUsageBit::CopySrc | + dawn::TextureUsageBit::CopyDst; + + if (GrRenderable::kYes == renderable) { + desc.usage |= dawn::TextureUsageBit::OutputAttachment; + } + + desc.size.width = width; + desc.size.height = height; + desc.size.depth = 1; + desc.format = format; + + // Figure out the number of mip levels. + if (GrMipMapped::kYes == mipMapped) { + desc.mipLevelCount = SkMipMap::ComputeLevelCount(width, height) + 1; + } + + dawn::Texture tex = this->device().CreateTexture(&desc); + + size_t bpp = GrBytesPerPixel(config); + size_t baseLayerSize = bpp * width * height; + SkAutoMalloc defaultStorage(baseLayerSize); + if (!pixels) { + // Fill in the texture with all zeros so we don't have random garbage + pixels = defaultStorage.get(); + memset(defaultStorage.get(), 0, baseLayerSize); + } + dawn::Device device = this->device(); + dawn::CommandEncoder copyEncoder = fDevice.CreateCommandEncoder(); + int w = width, h = height; + for (uint32_t i = 0; i < desc.mipLevelCount; i++) { + size_t origRowBytes = bpp * w; + size_t rowBytes = GrDawnRoundRowBytes(origRowBytes); + size_t size = rowBytes * h; + dawn::BufferDescriptor bufferDesc; + bufferDesc.size = size; + bufferDesc.usage = dawn::BufferUsageBit::CopySrc | dawn::BufferUsageBit::CopyDst; + dawn::Buffer buffer = this->device().CreateBuffer(&bufferDesc); + const uint8_t* src = static_cast(pixels); + if (rowBytes == origRowBytes) { + buffer.SetSubData(0, size, src); + } else { + uint32_t offset = 0; + for (int row = 0; row < h; row++) { + buffer.SetSubData(offset, origRowBytes, src); + offset += rowBytes; + src += origRowBytes; + } + } + dawn::BufferCopyView srcBuffer; + srcBuffer.buffer = buffer; + srcBuffer.offset = 0; + srcBuffer.rowPitch = rowBytes; + srcBuffer.imageHeight = h; + dawn::TextureCopyView dstTexture; + dstTexture.texture = tex; + dstTexture.mipLevel = i; + dstTexture.origin = {0, 0, 0}; + dawn::Extent3D copySize = {(uint32_t) w, (uint32_t) h, 1}; + copyEncoder.CopyBufferToTexture(&srcBuffer, &dstTexture, ©Size); + w = SkTMax(1, w / 2); + h = SkTMax(1, h / 2); + } + dawn::CommandBuffer cmdBuf = copyEncoder.Finish(); + fQueue.Submit(1, &cmdBuf); + GrDawnImageInfo info; + info.fTexture = tex; + info.fFormat = desc.format; + info.fLevelCount = desc.mipLevelCount; + return GrBackendTexture(width, height, info); } void GrDawnGpu::deleteBackendTexture(const GrBackendTexture& tex) { diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp index f156af3342..020207e19e 100644 --- a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp +++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp @@ -84,13 +84,19 @@ GrDawnGpuTextureCommandBuffer::~GrDawnGpuTextureCommandBuffer() {} //////////////////////////////////////////////////////////////////////////////// -dawn::LoadOp to_dawn_load_op(GrLoadOp loadOp) { +static dawn::LoadOp to_dawn_load_op(GrLoadOp loadOp) { switch (loadOp) { case GrLoadOp::kLoad: return dawn::LoadOp::Load; + case GrLoadOp::kDiscard: + // Use LoadOp::Load to emulate DontCare. + // Dawn doesn't have DontCare, for security reasons. + // Load should be equivalent to DontCare for desktop; Clear would + // probably be better for tilers. If Dawn does add DontCare + // as an extension, use it here. + return dawn::LoadOp::Load; case GrLoadOp::kClear: return dawn::LoadOp::Clear; - case GrLoadOp::kDiscard: default: SK_ABORT("Invalid LoadOp"); } @@ -255,6 +261,8 @@ static dawn::VertexFormat to_dawn_vertex_format(GrVertexAttribType type) { return dawn::VertexFormat::Float4; case kUShort2_GrVertexAttribType: return dawn::VertexFormat::UShort2; + case kInt_GrVertexAttribType: + return dawn::VertexFormat::Int; case kUByte4_norm_GrVertexAttribType: return dawn::VertexFormat::UChar4Norm; default: @@ -282,6 +290,24 @@ static dawn::PrimitiveTopology to_dawn_primitive_topology(GrPrimitiveType primit } } +void GrDawnGpuRTCommandBuffer::setScissorState( + const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays) { + SkIRect rect; + if (pipeline.isScissorEnabled()) { + constexpr SkIRect kBogusScissor{0, 0, 1, 1}; + rect = fixedDynamicState ? fixedDynamicState->fScissorRect : kBogusScissor; + if (kBottomLeft_GrSurfaceOrigin == fOrigin) { + rect.setXYWH(rect.x(), fRenderTarget->height() - rect.bottom(), + rect.width(), rect.height()); + } + } else { + rect = SkIRect::MakeWH(fRenderTarget->width(), fRenderTarget->height()); + } + fPassEncoder.SetScissorRect(rect.x(), rect.y(), rect.width(), rect.height()); +} + void GrDawnGpuRTCommandBuffer::applyState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrTextureProxy* const primProcProxies[], @@ -378,10 +404,15 @@ void GrDawnGpuRTCommandBuffer::applyState(const GrPipeline& pipeline, rpDesc.colorStates = colorStates; dawn::RenderPipeline renderPipeline = fGpu->device().CreateRenderPipeline(&rpDesc); fPassEncoder.SetPipeline(renderPipeline); - fPassEncoder.SetBindGroup(0, program->fUniformBindGroup, 0, nullptr); + fPassEncoder.SetBindGroup(0, program->fBindGroup, 0, nullptr); if (pipeline.isStencilEnabled()) { fPassEncoder.SetStencilReference(pipeline.getUserStencil()->fFront.fRef); } + GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo(); + const float* c = blendInfo.fBlendConstant.vec(); + dawn::Color color{c[0], c[1], c[2], c[3]}; + fPassEncoder.SetBlendColor(&color); + this->setScissorState(pipeline, fixedDynamicState, dynamicStateArrays); } void GrDawnGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.h b/src/gpu/dawn/GrDawnGpuCommandBuffer.h index 162f850f94..88dd877ef2 100644 --- a/src/gpu/dawn/GrDawnGpuCommandBuffer.h +++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.h @@ -64,6 +64,9 @@ public: private: GrGpu* gpu() override; + void setScissorState(const GrPipeline&, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays); void applyState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrTextureProxy* const primProcProxies[], diff --git a/src/gpu/dawn/GrDawnProgramBuilder.cpp b/src/gpu/dawn/GrDawnProgramBuilder.cpp index b72ee2644b..f0fe75979b 100644 --- a/src/gpu/dawn/GrDawnProgramBuilder.cpp +++ b/src/gpu/dawn/GrDawnProgramBuilder.cpp @@ -11,11 +11,13 @@ #include "src/gpu/GrShaderUtils.h" #include "src/gpu/GrStencilSettings.h" #include "src/gpu/dawn/GrDawnGpu.h" +#include "src/gpu/dawn/GrDawnTexture.h" #include "src/sksl/SkSLCompiler.h" static SkSL::String sksl_to_spirv(const GrDawnGpu* gpu, const char* shaderString, SkSL::Program::Kind kind, SkSL::Program::Inputs* inputs) { SkSL::Program::Settings settings; + settings.fCaps = gpu->caps()->shaderCaps(); std::unique_ptr program = gpu->shaderCompiler()->convertProgram( kind, shaderString, @@ -149,6 +151,35 @@ static dawn::StencilOperation to_dawn_stencil_operation(GrStencilOp op) { } } +static dawn::FilterMode to_dawn_filter_mode(GrSamplerState::Filter filter) { + switch (filter) { + case GrSamplerState::Filter::kNearest: + return dawn::FilterMode::Nearest; + case GrSamplerState::Filter::kBilerp: + case GrSamplerState::Filter::kMipMap: + return dawn::FilterMode::Linear; + default: + SkASSERT(!"unsupported filter mode"); + return dawn::FilterMode::Nearest; + } +} + +static dawn::AddressMode to_dawn_address_mode(GrSamplerState::WrapMode wrapMode) { + switch (wrapMode) { + case GrSamplerState::WrapMode::kClamp: + return dawn::AddressMode::ClampToEdge; + case GrSamplerState::WrapMode::kClampToBorder: + // TODO: unsupported + return dawn::AddressMode::ClampToEdge; + case GrSamplerState::WrapMode::kRepeat: + return dawn::AddressMode::Repeat; + case GrSamplerState::WrapMode::kMirrorRepeat: + return dawn::AddressMode::MirrorRepeat; + } + SkASSERT(!"unsupported address mode"); + return dawn::AddressMode::ClampToEdge; +} + static dawn::ColorStateDescriptor create_color_state(const GrDawnGpu* gpu, const GrPipeline& pipeline, dawn::TextureFormat colorFormat) { @@ -215,6 +246,19 @@ static dawn::DepthStencilStateDescriptor create_depth_stencil_state( return state; } +static dawn::Sampler create_sampler(const GrDawnGpu* gpu, const GrSamplerState& samplerState) { + dawn::SamplerDescriptor desc; + desc.addressModeU = to_dawn_address_mode(samplerState.wrapModeX()); + desc.addressModeV = to_dawn_address_mode(samplerState.wrapModeY()); + desc.addressModeW = dawn::AddressMode::ClampToEdge; + desc.magFilter = desc.minFilter = to_dawn_filter_mode(samplerState.filter()); + desc.mipmapFilter = dawn::FilterMode::Linear; + desc.lodMinClamp = 0.0f; + desc.lodMaxClamp = 1000.0f; + desc.compare = dawn::CompareFunction::Never; + return gpu->device().CreateSampler(&desc); +} + static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const dawn::Buffer& buffer, uint32_t offset, uint32_t size, const dawn::Sampler& sampler, @@ -234,6 +278,16 @@ static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const da return make_bind_group_binding(binding, buffer, offset, size, nullptr, nullptr); } +static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, + const dawn::Sampler& sampler) { + return make_bind_group_binding(binding, nullptr, 0, 0, sampler, nullptr); +} + +static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, + const dawn::TextureView& textureView) { + return make_bind_group_binding(binding, nullptr, 0, 0, nullptr, textureView); +} + sk_sp GrDawnProgramBuilder::Build(GrDawnGpu* gpu, GrRenderTarget* renderTarget, GrSurfaceOrigin origin, @@ -273,40 +327,74 @@ sk_sp GrDawnProgramBuilder::Build(GrDawnGpu* gpu, result->fFragmentProcessorCnt = builder.fFragmentProcessorCnt; std::vector layoutBindings; std::vector bindings; - + if (0 != geometryUniformSize) { + layoutBindings.push_back({ GrDawnUniformHandler::kGeometryBinding, + dawn::ShaderStageBit::Vertex, + dawn::BindingType::UniformBuffer}); + } + if (0 != fragmentUniformSize) { + layoutBindings.push_back({ GrDawnUniformHandler::kFragBinding, + dawn::ShaderStageBit::Fragment, + dawn::BindingType::UniformBuffer}); + } + uint32_t binding = GrDawnUniformHandler::kSamplerBindingBase; + for (int i = 0; i < builder.fUniformHandler.fSamplers.count(); ++i) { + layoutBindings.push_back({ binding++, dawn::ShaderStageBit::Fragment, + dawn::BindingType::Sampler}); + layoutBindings.push_back({ binding++, dawn::ShaderStageBit::Fragment, + dawn::BindingType::SampledTexture}); + } + dawn::BindGroupLayoutDescriptor bindGroupLayoutDesc; + bindGroupLayoutDesc.bindingCount = layoutBindings.size(); + bindGroupLayoutDesc.bindings = layoutBindings.data(); + auto bindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc); + dawn::PipelineLayoutDescriptor pipelineLayoutDesc; + pipelineLayoutDesc.bindGroupLayoutCount = 1; + pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout; + 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(0, result->fGeometryUniformBuffer, 0, - geometryUniformSize)); - layoutBindings.push_back({ 0, dawn::ShaderStageBit::Vertex, - dawn::BindingType::UniformBuffer}); + 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(1, result->fFragmentUniformBuffer, 0, - fragmentUniformSize)); - layoutBindings.push_back({ 1, dawn::ShaderStageBit::Fragment, - dawn::BindingType::UniformBuffer}); + bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kFragBinding, + result->fFragmentUniformBuffer, + 0, fragmentUniformSize)); } - dawn::BindGroupLayoutDescriptor bindGroupLayoutDesc; - bindGroupLayoutDesc.bindingCount = layoutBindings.size(); - bindGroupLayoutDesc.bindings = layoutBindings.data(); - auto bindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc); - dawn::BindGroupDescriptor descriptor; - descriptor.layout = bindGroupLayout; - descriptor.bindingCount = bindings.size(); - descriptor.bindings = bindings.data(); - result->fUniformBindGroup = gpu->device().CreateBindGroup(&descriptor); - dawn::PipelineLayoutDescriptor pipelineLayoutDesc; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout; - result->fPipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc); + 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; diff --git a/src/gpu/dawn/GrDawnProgramBuilder.h b/src/gpu/dawn/GrDawnProgramBuilder.h index 5227e4c97d..319dff9712 100644 --- a/src/gpu/dawn/GrDawnProgramBuilder.h +++ b/src/gpu/dawn/GrDawnProgramBuilder.h @@ -63,7 +63,7 @@ struct GrDawnProgram : public SkRefCnt { dawn::Buffer fGeometryUniformBuffer; dawn::Buffer fFragmentUniformBuffer; dawn::PipelineLayout fPipelineLayout; - dawn::BindGroup fUniformBindGroup; + dawn::BindGroup fBindGroup; dawn::ColorStateDescriptor fColorState; dawn::DepthStencilStateDescriptor fDepthStencilState; GrDawnProgramDataManager fDataManager; diff --git a/src/gpu/dawn/GrDawnUniformHandler.cpp b/src/gpu/dawn/GrDawnUniformHandler.cpp index 9fcd22485f..f323cdfc03 100644 --- a/src/gpu/dawn/GrDawnUniformHandler.cpp +++ b/src/gpu/dawn/GrDawnUniformHandler.cpp @@ -11,6 +11,8 @@ GrDawnUniformHandler::GrDawnUniformHandler(GrGLSLProgramBuilder* program) : INHERITED(program) , fUniforms(kUniformsPerBlock) + , fSamplers(kUniformsPerBlock) + , fTextures(kUniformsPerBlock) { } @@ -236,24 +238,62 @@ GrGLSLUniformHandler::SamplerHandle GrDawnUniformHandler::addSampler(const GrTex const GrSwizzle& swizzle, const char* name, const GrShaderCaps* caps) { - SkASSERT(!"unimplemented"); - SkASSERT(name && strlen(name)); + SkString mangleName; + char prefix = 's'; + fProgramBuilder->nameVariable(&mangleName, prefix, name, true); - return GrGLSLUniformHandler::SamplerHandle(0); + GrSLType samplerType = kSampler_GrSLType, textureType = kTexture2D_GrSLType; + int binding = kSamplerBindingBase + fSamplers.count() * 2; + UniformInfo& info = fSamplers.push_back(); + info.fVar.setType(samplerType); + info.fVar.setTypeModifier(GrShaderVar::kUniform_TypeModifier); + info.fVar.setName(mangleName); + SkString layoutQualifier; + layoutQualifier.appendf("set = 0, binding = %d", binding); + info.fVar.addLayoutQualifier(layoutQualifier.c_str()); + info.fVisibility = kFragment_GrShaderFlag; + info.fUBOOffset = 0; + fSamplerSwizzles.push_back(swizzle); + SkASSERT(fSamplerSwizzles.count() == fSamplers.count()); + + SkString mangleTexName; + char texPrefix = 't'; + fProgramBuilder->nameVariable(&mangleTexName, texPrefix, name, true); + UniformInfo& texInfo = fTextures.push_back(); + texInfo.fVar.setType(textureType); + texInfo.fVar.setTypeModifier(GrShaderVar::kUniform_TypeModifier); + texInfo.fVar.setName(mangleTexName); + SkString texLayoutQualifier; + texLayoutQualifier.appendf("set = 0, binding = %d", binding + 1); + texInfo.fVar.addLayoutQualifier(texLayoutQualifier.c_str()); + texInfo.fVisibility = kFragment_GrShaderFlag; + texInfo.fUBOOffset = 0; + + SkString reference; + reference.printf("makeSampler2D(%s, %s)", texInfo.fVar.getName().c_str(), + info.fVar.getName().c_str()); + fSamplerReferences.push_back() = reference; + return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1); } const char* GrDawnUniformHandler::samplerVariable( GrGLSLUniformHandler::SamplerHandle handle) const { - SkASSERT(!"unimplemented"); - return ""; + return fSamplerReferences[handle.toIndex()].c_str(); } GrSwizzle GrDawnUniformHandler::samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const { - SkASSERT(!"unimplemented"); - return GrSwizzle(); + return fSamplerSwizzles[handle.toIndex()]; } void GrDawnUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { + for (int i = 0; i < fSamplers.count(); ++i) { + if (fSamplers[i].fVisibility & visibility) { + fSamplers[i].fVar.appendDecl(fProgramBuilder->shaderCaps(), out); + out->append(";\n"); + fTextures[i].fVar.appendDecl(fProgramBuilder->shaderCaps(), out); + out->append(";\n"); + } + } SkString uniformsString; for (int i = 0; i < fUniforms.count(); ++i) { if (fUniforms[i].fVisibility & visibility) { @@ -275,8 +315,8 @@ void GrDawnUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString uniformBinding = kFragBinding; stage = "fragment"; } - out->appendf("layout (set = %d, binding = %d) uniform %sUniformBuffer\n{\n", - kUniformBufferBindGroup, uniformBinding, stage); + out->appendf("layout (set = 0, binding = %d) uniform %sUniformBuffer\n{\n", + uniformBinding, stage); out->appendf("%s\n};\n", uniformsString.c_str()); } } diff --git a/src/gpu/dawn/GrDawnUniformHandler.h b/src/gpu/dawn/GrDawnUniformHandler.h index 50bd863317..1cc813b608 100644 --- a/src/gpu/dawn/GrDawnUniformHandler.h +++ b/src/gpu/dawn/GrDawnUniformHandler.h @@ -20,11 +20,6 @@ public: const GrShaderVar& getUniformVariable(UniformHandle u) const override; const char* getUniformCStr(UniformHandle u) const override; - enum { - kUniformBufferBindGroup = 0, - kSamplerBindGroup = 1, - kTexelBufferBindGroup = 2, - }; struct UniformInfo { GrShaderVar fVar; int fUBOOffset; @@ -34,6 +29,7 @@ public: enum { kGeometryBinding = 0, kFragBinding = 1, + kSamplerBindingBase = 2, }; private: @@ -51,8 +47,12 @@ private: int arrayCount, const char** outName) override; - GrShaderVar fDummyVar; - UniformInfoArray fUniforms; + UniformInfoArray fUniforms; + UniformInfoArray fSamplers; + UniformInfoArray fTextures; + SkTArray fSamplerSwizzles; + SkTArray fSamplerReferences; + uint32_t fCurrentGeometryUBOOffset = 0; uint32_t fCurrentFragmentUBOOffset = 0; diff --git a/src/gpu/dawn/GrDawnUtil.cpp b/src/gpu/dawn/GrDawnUtil.cpp index 7d9df0d8ad..b23f44a038 100644 --- a/src/gpu/dawn/GrDawnUtil.cpp +++ b/src/gpu/dawn/GrDawnUtil.cpp @@ -40,6 +40,7 @@ bool GrPixelConfigToDawnFormat(GrPixelConfig config, dawn::TextureFormat* format *format = dawn::TextureFormat::BGRA8Unorm; return true; case kAlpha_8_GrPixelConfig: + case kAlpha_8_as_Red_GrPixelConfig: *format = dawn::TextureFormat::R8Unorm; return true; default: