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 <egdaniel@google.com> Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
parent
4bdcbc2704
commit
170d9905cc
@ -8,12 +8,22 @@
|
|||||||
#include "src/gpu/dawn/GrDawnCaps.h"
|
#include "src/gpu/dawn/GrDawnCaps.h"
|
||||||
|
|
||||||
GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) {
|
GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) {
|
||||||
|
fMipMapSupport = true;
|
||||||
fBufferMapThreshold = SK_MaxS32; // FIXME: get this from Dawn?
|
fBufferMapThreshold = SK_MaxS32; // FIXME: get this from Dawn?
|
||||||
fShaderCaps.reset(new GrShaderCaps(contextOptions));
|
fShaderCaps.reset(new GrShaderCaps(contextOptions));
|
||||||
fMaxTextureSize = 2048; // FIXME
|
fMaxTextureSize = fMaxRenderTargetSize = 4096; // FIXME
|
||||||
fMaxVertexAttributes = 16; // FIXME
|
fMaxVertexAttributes = 16; // FIXME
|
||||||
|
fClampToBorderSupport = false;
|
||||||
fPerformPartialClearsAsDraws = true;
|
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);
|
this->applyOptionsOverrides(contextOptions);
|
||||||
fShaderCaps->applyOptionsOverrides(contextOptions);
|
fShaderCaps->applyOptionsOverrides(contextOptions);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,10 @@
|
|||||||
#include "src/gpu/dawn/GrDawnRenderTarget.h"
|
#include "src/gpu/dawn/GrDawnRenderTarget.h"
|
||||||
#include "src/gpu/dawn/GrDawnStencilAttachment.h"
|
#include "src/gpu/dawn/GrDawnStencilAttachment.h"
|
||||||
#include "src/gpu/dawn/GrDawnTexture.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"
|
#include "src/sksl/SkSLCompiler.h"
|
||||||
|
|
||||||
#if !defined(SK_BUILD_FOR_WIN)
|
#if !defined(SK_BUILD_FOR_WIN)
|
||||||
@ -222,15 +225,102 @@ GrStencilAttachment* GrDawnGpu::createStencilAttachmentForRenderTarget(const GrR
|
|||||||
}
|
}
|
||||||
|
|
||||||
GrBackendTexture GrDawnGpu::createBackendTexture(int width, int height,
|
GrBackendTexture GrDawnGpu::createBackendTexture(int width, int height,
|
||||||
const GrBackendFormat& format,
|
const GrBackendFormat& backendFormat,
|
||||||
GrMipMapped mipMapped,
|
GrMipMapped mipMapped,
|
||||||
GrRenderable renderable,
|
GrRenderable renderable,
|
||||||
const void* pixels,
|
const void* pixels,
|
||||||
size_t rowBytes,
|
size_t rowBytes,
|
||||||
const SkColor4f* color,
|
const SkColor4f* color,
|
||||||
GrProtected isProtected) {
|
GrProtected isProtected) {
|
||||||
SkASSERT(!"unimplemented");
|
dawn::TextureFormat format;
|
||||||
return GrBackendTexture();
|
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<const uint8_t*>(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) {
|
void GrDawnGpu::deleteBackendTexture(const GrBackendTexture& tex) {
|
||||||
|
@ -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) {
|
switch (loadOp) {
|
||||||
case GrLoadOp::kLoad:
|
case GrLoadOp::kLoad:
|
||||||
return dawn::LoadOp::Load;
|
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:
|
case GrLoadOp::kClear:
|
||||||
return dawn::LoadOp::Clear;
|
return dawn::LoadOp::Clear;
|
||||||
case GrLoadOp::kDiscard:
|
|
||||||
default:
|
default:
|
||||||
SK_ABORT("Invalid LoadOp");
|
SK_ABORT("Invalid LoadOp");
|
||||||
}
|
}
|
||||||
@ -255,6 +261,8 @@ static dawn::VertexFormat to_dawn_vertex_format(GrVertexAttribType type) {
|
|||||||
return dawn::VertexFormat::Float4;
|
return dawn::VertexFormat::Float4;
|
||||||
case kUShort2_GrVertexAttribType:
|
case kUShort2_GrVertexAttribType:
|
||||||
return dawn::VertexFormat::UShort2;
|
return dawn::VertexFormat::UShort2;
|
||||||
|
case kInt_GrVertexAttribType:
|
||||||
|
return dawn::VertexFormat::Int;
|
||||||
case kUByte4_norm_GrVertexAttribType:
|
case kUByte4_norm_GrVertexAttribType:
|
||||||
return dawn::VertexFormat::UChar4Norm;
|
return dawn::VertexFormat::UChar4Norm;
|
||||||
default:
|
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,
|
void GrDawnGpuRTCommandBuffer::applyState(const GrPipeline& pipeline,
|
||||||
const GrPrimitiveProcessor& primProc,
|
const GrPrimitiveProcessor& primProc,
|
||||||
const GrTextureProxy* const primProcProxies[],
|
const GrTextureProxy* const primProcProxies[],
|
||||||
@ -378,10 +404,15 @@ void GrDawnGpuRTCommandBuffer::applyState(const GrPipeline& pipeline,
|
|||||||
rpDesc.colorStates = colorStates;
|
rpDesc.colorStates = colorStates;
|
||||||
dawn::RenderPipeline renderPipeline = fGpu->device().CreateRenderPipeline(&rpDesc);
|
dawn::RenderPipeline renderPipeline = fGpu->device().CreateRenderPipeline(&rpDesc);
|
||||||
fPassEncoder.SetPipeline(renderPipeline);
|
fPassEncoder.SetPipeline(renderPipeline);
|
||||||
fPassEncoder.SetBindGroup(0, program->fUniformBindGroup, 0, nullptr);
|
fPassEncoder.SetBindGroup(0, program->fBindGroup, 0, nullptr);
|
||||||
if (pipeline.isStencilEnabled()) {
|
if (pipeline.isStencilEnabled()) {
|
||||||
fPassEncoder.SetStencilReference(pipeline.getUserStencil()->fFront.fRef);
|
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,
|
void GrDawnGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc,
|
||||||
|
@ -64,6 +64,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
GrGpu* gpu() override;
|
GrGpu* gpu() override;
|
||||||
|
|
||||||
|
void setScissorState(const GrPipeline&,
|
||||||
|
const GrPipeline::FixedDynamicState* fixedDynamicState,
|
||||||
|
const GrPipeline::DynamicStateArrays* dynamicStateArrays);
|
||||||
void applyState(const GrPipeline& pipeline,
|
void applyState(const GrPipeline& pipeline,
|
||||||
const GrPrimitiveProcessor& primProc,
|
const GrPrimitiveProcessor& primProc,
|
||||||
const GrTextureProxy* const primProcProxies[],
|
const GrTextureProxy* const primProcProxies[],
|
||||||
|
@ -11,11 +11,13 @@
|
|||||||
#include "src/gpu/GrShaderUtils.h"
|
#include "src/gpu/GrShaderUtils.h"
|
||||||
#include "src/gpu/GrStencilSettings.h"
|
#include "src/gpu/GrStencilSettings.h"
|
||||||
#include "src/gpu/dawn/GrDawnGpu.h"
|
#include "src/gpu/dawn/GrDawnGpu.h"
|
||||||
|
#include "src/gpu/dawn/GrDawnTexture.h"
|
||||||
#include "src/sksl/SkSLCompiler.h"
|
#include "src/sksl/SkSLCompiler.h"
|
||||||
|
|
||||||
static SkSL::String sksl_to_spirv(const GrDawnGpu* gpu, const char* shaderString,
|
static SkSL::String sksl_to_spirv(const GrDawnGpu* gpu, const char* shaderString,
|
||||||
SkSL::Program::Kind kind, SkSL::Program::Inputs* inputs) {
|
SkSL::Program::Kind kind, SkSL::Program::Inputs* inputs) {
|
||||||
SkSL::Program::Settings settings;
|
SkSL::Program::Settings settings;
|
||||||
|
settings.fCaps = gpu->caps()->shaderCaps();
|
||||||
std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
|
std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
|
||||||
kind,
|
kind,
|
||||||
shaderString,
|
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,
|
static dawn::ColorStateDescriptor create_color_state(const GrDawnGpu* gpu,
|
||||||
const GrPipeline& pipeline,
|
const GrPipeline& pipeline,
|
||||||
dawn::TextureFormat colorFormat) {
|
dawn::TextureFormat colorFormat) {
|
||||||
@ -215,6 +246,19 @@ static dawn::DepthStencilStateDescriptor create_depth_stencil_state(
|
|||||||
return 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,
|
static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const dawn::Buffer& buffer,
|
||||||
uint32_t offset, uint32_t size, const
|
uint32_t offset, uint32_t size, const
|
||||||
dawn::Sampler& sampler,
|
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);
|
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<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
|
sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
|
||||||
GrRenderTarget* renderTarget,
|
GrRenderTarget* renderTarget,
|
||||||
GrSurfaceOrigin origin,
|
GrSurfaceOrigin origin,
|
||||||
@ -273,40 +327,74 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
|
|||||||
result->fFragmentProcessorCnt = builder.fFragmentProcessorCnt;
|
result->fFragmentProcessorCnt = builder.fFragmentProcessorCnt;
|
||||||
std::vector<dawn::BindGroupLayoutBinding> layoutBindings;
|
std::vector<dawn::BindGroupLayoutBinding> layoutBindings;
|
||||||
std::vector<dawn::BindGroupBinding> bindings;
|
std::vector<dawn::BindGroupBinding> 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) {
|
if (0 != geometryUniformSize) {
|
||||||
dawn::BufferDescriptor desc;
|
dawn::BufferDescriptor desc;
|
||||||
desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
|
desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
|
||||||
desc.size = geometryUniformSize;
|
desc.size = geometryUniformSize;
|
||||||
result->fGeometryUniformBuffer = gpu->device().CreateBuffer(&desc);
|
result->fGeometryUniformBuffer = gpu->device().CreateBuffer(&desc);
|
||||||
bindings.push_back(make_bind_group_binding(0, result->fGeometryUniformBuffer, 0,
|
bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kGeometryBinding,
|
||||||
geometryUniformSize));
|
result->fGeometryUniformBuffer,
|
||||||
layoutBindings.push_back({ 0, dawn::ShaderStageBit::Vertex,
|
0, geometryUniformSize));
|
||||||
dawn::BindingType::UniformBuffer});
|
|
||||||
}
|
}
|
||||||
if (0 != fragmentUniformSize) {
|
if (0 != fragmentUniformSize) {
|
||||||
dawn::BufferDescriptor desc;
|
dawn::BufferDescriptor desc;
|
||||||
desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
|
desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
|
||||||
desc.size = fragmentUniformSize;
|
desc.size = fragmentUniformSize;
|
||||||
result->fFragmentUniformBuffer = gpu->device().CreateBuffer(&desc);
|
result->fFragmentUniformBuffer = gpu->device().CreateBuffer(&desc);
|
||||||
bindings.push_back(make_bind_group_binding(1, result->fFragmentUniformBuffer, 0,
|
bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kFragBinding,
|
||||||
fragmentUniformSize));
|
result->fFragmentUniformBuffer,
|
||||||
layoutBindings.push_back({ 1, dawn::ShaderStageBit::Fragment,
|
0, fragmentUniformSize));
|
||||||
dawn::BindingType::UniformBuffer});
|
|
||||||
}
|
}
|
||||||
dawn::BindGroupLayoutDescriptor bindGroupLayoutDesc;
|
binding = GrDawnUniformHandler::kSamplerBindingBase;
|
||||||
bindGroupLayoutDesc.bindingCount = layoutBindings.size();
|
for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
|
||||||
bindGroupLayoutDesc.bindings = layoutBindings.data();
|
dawn::Sampler sampler = create_sampler(gpu, primProc.textureSampler(i).samplerState());
|
||||||
auto bindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc);
|
bindings.push_back(make_bind_group_binding(binding++, sampler));
|
||||||
dawn::BindGroupDescriptor descriptor;
|
GrDawnTexture* tex = static_cast<GrDawnTexture*>(primProcProxies[i]->peekTexture());
|
||||||
descriptor.layout = bindGroupLayout;
|
dawn::TextureView textureView = tex->textureView();
|
||||||
descriptor.bindingCount = bindings.size();
|
bindings.push_back(make_bind_group_binding(binding++, textureView));
|
||||||
descriptor.bindings = bindings.data();
|
}
|
||||||
result->fUniformBindGroup = gpu->device().CreateBindGroup(&descriptor);
|
GrFragmentProcessor::Iter iter(pipeline);
|
||||||
dawn::PipelineLayoutDescriptor pipelineLayoutDesc;
|
const GrFragmentProcessor* fp = iter.next();
|
||||||
pipelineLayoutDesc.bindGroupLayoutCount = 1;
|
while (fp) {
|
||||||
pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
|
for (int i = 0; i < fp->numTextureSamplers(); ++i) {
|
||||||
result->fPipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
|
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->fBuiltinUniformHandles = builder.fUniformHandles;
|
||||||
result->fColorState = create_color_state(gpu, pipeline, colorFormat);
|
result->fColorState = create_color_state(gpu, pipeline, colorFormat);
|
||||||
GrStencilSettings stencil;
|
GrStencilSettings stencil;
|
||||||
|
@ -63,7 +63,7 @@ struct GrDawnProgram : public SkRefCnt {
|
|||||||
dawn::Buffer fGeometryUniformBuffer;
|
dawn::Buffer fGeometryUniformBuffer;
|
||||||
dawn::Buffer fFragmentUniformBuffer;
|
dawn::Buffer fFragmentUniformBuffer;
|
||||||
dawn::PipelineLayout fPipelineLayout;
|
dawn::PipelineLayout fPipelineLayout;
|
||||||
dawn::BindGroup fUniformBindGroup;
|
dawn::BindGroup fBindGroup;
|
||||||
dawn::ColorStateDescriptor fColorState;
|
dawn::ColorStateDescriptor fColorState;
|
||||||
dawn::DepthStencilStateDescriptor fDepthStencilState;
|
dawn::DepthStencilStateDescriptor fDepthStencilState;
|
||||||
GrDawnProgramDataManager fDataManager;
|
GrDawnProgramDataManager fDataManager;
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
GrDawnUniformHandler::GrDawnUniformHandler(GrGLSLProgramBuilder* program)
|
GrDawnUniformHandler::GrDawnUniformHandler(GrGLSLProgramBuilder* program)
|
||||||
: INHERITED(program)
|
: INHERITED(program)
|
||||||
, fUniforms(kUniformsPerBlock)
|
, fUniforms(kUniformsPerBlock)
|
||||||
|
, fSamplers(kUniformsPerBlock)
|
||||||
|
, fTextures(kUniformsPerBlock)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,24 +238,62 @@ GrGLSLUniformHandler::SamplerHandle GrDawnUniformHandler::addSampler(const GrTex
|
|||||||
const GrSwizzle& swizzle,
|
const GrSwizzle& swizzle,
|
||||||
const char* name,
|
const char* name,
|
||||||
const GrShaderCaps* caps) {
|
const GrShaderCaps* caps) {
|
||||||
SkASSERT(!"unimplemented");
|
SkString mangleName;
|
||||||
SkASSERT(name && strlen(name));
|
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(
|
const char* GrDawnUniformHandler::samplerVariable(
|
||||||
GrGLSLUniformHandler::SamplerHandle handle) const {
|
GrGLSLUniformHandler::SamplerHandle handle) const {
|
||||||
SkASSERT(!"unimplemented");
|
return fSamplerReferences[handle.toIndex()].c_str();
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrSwizzle GrDawnUniformHandler::samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const {
|
GrSwizzle GrDawnUniformHandler::samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const {
|
||||||
SkASSERT(!"unimplemented");
|
return fSamplerSwizzles[handle.toIndex()];
|
||||||
return GrSwizzle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrDawnUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
|
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;
|
SkString uniformsString;
|
||||||
for (int i = 0; i < fUniforms.count(); ++i) {
|
for (int i = 0; i < fUniforms.count(); ++i) {
|
||||||
if (fUniforms[i].fVisibility & visibility) {
|
if (fUniforms[i].fVisibility & visibility) {
|
||||||
@ -275,8 +315,8 @@ void GrDawnUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString
|
|||||||
uniformBinding = kFragBinding;
|
uniformBinding = kFragBinding;
|
||||||
stage = "fragment";
|
stage = "fragment";
|
||||||
}
|
}
|
||||||
out->appendf("layout (set = %d, binding = %d) uniform %sUniformBuffer\n{\n",
|
out->appendf("layout (set = 0, binding = %d) uniform %sUniformBuffer\n{\n",
|
||||||
kUniformBufferBindGroup, uniformBinding, stage);
|
uniformBinding, stage);
|
||||||
out->appendf("%s\n};\n", uniformsString.c_str());
|
out->appendf("%s\n};\n", uniformsString.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,6 @@ public:
|
|||||||
const GrShaderVar& getUniformVariable(UniformHandle u) const override;
|
const GrShaderVar& getUniformVariable(UniformHandle u) const override;
|
||||||
const char* getUniformCStr(UniformHandle u) const override;
|
const char* getUniformCStr(UniformHandle u) const override;
|
||||||
|
|
||||||
enum {
|
|
||||||
kUniformBufferBindGroup = 0,
|
|
||||||
kSamplerBindGroup = 1,
|
|
||||||
kTexelBufferBindGroup = 2,
|
|
||||||
};
|
|
||||||
struct UniformInfo {
|
struct UniformInfo {
|
||||||
GrShaderVar fVar;
|
GrShaderVar fVar;
|
||||||
int fUBOOffset;
|
int fUBOOffset;
|
||||||
@ -34,6 +29,7 @@ public:
|
|||||||
enum {
|
enum {
|
||||||
kGeometryBinding = 0,
|
kGeometryBinding = 0,
|
||||||
kFragBinding = 1,
|
kFragBinding = 1,
|
||||||
|
kSamplerBindingBase = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -51,8 +47,12 @@ private:
|
|||||||
int arrayCount,
|
int arrayCount,
|
||||||
const char** outName) override;
|
const char** outName) override;
|
||||||
|
|
||||||
GrShaderVar fDummyVar;
|
UniformInfoArray fUniforms;
|
||||||
UniformInfoArray fUniforms;
|
UniformInfoArray fSamplers;
|
||||||
|
UniformInfoArray fTextures;
|
||||||
|
SkTArray<GrSwizzle> fSamplerSwizzles;
|
||||||
|
SkTArray<SkString> fSamplerReferences;
|
||||||
|
|
||||||
uint32_t fCurrentGeometryUBOOffset = 0;
|
uint32_t fCurrentGeometryUBOOffset = 0;
|
||||||
uint32_t fCurrentFragmentUBOOffset = 0;
|
uint32_t fCurrentFragmentUBOOffset = 0;
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ bool GrPixelConfigToDawnFormat(GrPixelConfig config, dawn::TextureFormat* format
|
|||||||
*format = dawn::TextureFormat::BGRA8Unorm;
|
*format = dawn::TextureFormat::BGRA8Unorm;
|
||||||
return true;
|
return true;
|
||||||
case kAlpha_8_GrPixelConfig:
|
case kAlpha_8_GrPixelConfig:
|
||||||
|
case kAlpha_8_as_Red_GrPixelConfig:
|
||||||
*format = dawn::TextureFormat::R8Unorm;
|
*format = dawn::TextureFormat::R8Unorm;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user