From 170d9905cc7c4351260b4cd1b78ae1bbee3e02a5 Mon Sep 17 00:00:00 2001 From: Stephen White Date: Thu, 15 Aug 2019 16:48:24 -0400 Subject: [PATCH] Dawn: implement textures & samplers. Add samplers to Dawn binding group layout. Convert filter modes from Gr to Dawn. Rename fUniformBindGroup to fBindGroup (since it does more than uniforms now). Split combined samplers into separate textures and samplers bindings; recombine in the shader with makeSampler(). Create complete bind group layout before creating UBOs. Implement scissor rect. Set blend color in command buffer. Pass shader caps to SkSL. Enable flat interpolation, integer support, derivative support in Dawn Caps. Reduce the Dawn caps to 6 fragment/sampler combos. Add support for Int (1) vertex format. Change-Id: Id5e9060855f0dfc8c071f84ea6c456aba2a72b35 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/233977 Reviewed-by: Greg Daniel Commit-Queue: Stephen White --- src/gpu/dawn/GrDawnCaps.cpp | 12 ++- src/gpu/dawn/GrDawnGpu.cpp | 96 ++++++++++++++++- src/gpu/dawn/GrDawnGpuCommandBuffer.cpp | 37 ++++++- src/gpu/dawn/GrDawnGpuCommandBuffer.h | 3 + src/gpu/dawn/GrDawnProgramBuilder.cpp | 132 ++++++++++++++++++++---- src/gpu/dawn/GrDawnProgramBuilder.h | 2 +- src/gpu/dawn/GrDawnUniformHandler.cpp | 58 +++++++++-- src/gpu/dawn/GrDawnUniformHandler.h | 14 +-- src/gpu/dawn/GrDawnUtil.cpp | 1 + 9 files changed, 309 insertions(+), 46 deletions(-) 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: