1 /*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/dawn/GrDawnCaps.h"
9
10 #include "src/gpu/GrProgramDesc.h"
11 #include "src/gpu/GrProgramInfo.h"
12 #include "src/gpu/GrRenderTarget.h"
13 #include "src/gpu/GrStencilSettings.h"
14
GrDawnCaps(const GrContextOptions & contextOptions)15 GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) {
16 fMipmapSupport = true;
17 fBufferMapThreshold = SK_MaxS32; // FIXME: get this from Dawn?
18 fShaderCaps = std::make_unique<GrShaderCaps>();
19 fMaxTextureSize = fMaxRenderTargetSize = 8192; // FIXME
20 fMaxVertexAttributes = 16; // FIXME
21 fClampToBorderSupport = false;
22 fPerformPartialClearsAsDraws = true;
23 fDynamicStateArrayGeometryProcessorTextureSupport = true;
24
25 fShaderCaps->fFlatInterpolationSupport = true;
26 fShaderCaps->fIntegerSupport = true;
27 // FIXME: each fragment sampler takes two binding slots in Dawn (sampler + texture). Limit to
28 // 6 * 2 = 12, since kMaxBindingsPerGroup is 16 in Dawn, and we need to keep a few for
29 // non-texture bindings. Eventually, we may be able to increase kMaxBindingsPerGroup in Dawn.
30 fShaderCaps->fMaxFragmentSamplers = 6;
31 fShaderCaps->fShaderDerivativeSupport = true;
32
33 this->finishInitialization(contextOptions);
34 }
35
isFormatSRGB(const GrBackendFormat & format) const36 bool GrDawnCaps::isFormatSRGB(const GrBackendFormat& format) const {
37 return false;
38 }
39
isFormatTexturable(const GrBackendFormat & format,GrTextureType) const40 bool GrDawnCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const {
41 // Currently, all the formats in GrDawnFormatToPixelConfig are texturable.
42 wgpu::TextureFormat dawnFormat;
43 return format.asDawnFormat(&dawnFormat);
44 }
45
get_swizzle(const GrBackendFormat & format,GrColorType colorType,bool forOutput)46 static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
47 bool forOutput) {
48 switch (colorType) {
49 case GrColorType::kAlpha_8: // fall through
50 case GrColorType::kAlpha_F16:
51 if (forOutput) {
52 return GrSwizzle("a000");
53 } else {
54 return GrSwizzle("000r");
55 }
56 case GrColorType::kGray_8:
57 if (!forOutput) {
58 return GrSwizzle::RRRA();
59 }
60 break;
61 case GrColorType::kRGB_888x:
62 if (!forOutput) {
63 return GrSwizzle::RGB1();
64 }
65 break;
66 default:
67 return GrSwizzle::RGBA();
68 }
69 return GrSwizzle::RGBA();
70 }
71
isFormatRenderable(const GrBackendFormat & format,int sampleCount) const72 bool GrDawnCaps::isFormatRenderable(const GrBackendFormat& format,
73 int sampleCount) const {
74 wgpu::TextureFormat dawnFormat;
75 if (!format.isValid() || sampleCount > 1 || !format.asDawnFormat(&dawnFormat)) {
76 return false;
77 }
78
79 return GrDawnFormatIsRenderable(dawnFormat);
80 }
81
isFormatAsColorTypeRenderable(GrColorType ct,const GrBackendFormat & format,int sampleCount) const82 bool GrDawnCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
83 int sampleCount) const {
84 return isFormatRenderable(format, sampleCount);
85 }
86
surfaceSupportsReadPixels(const GrSurface * surface) const87 GrCaps::SurfaceReadPixelsSupport GrDawnCaps::surfaceSupportsReadPixels(
88 const GrSurface* surface) const {
89 // We currently support readbacks only from Textures and TextureRenderTargets.
90 return surface->asTexture() ? SurfaceReadPixelsSupport::kSupported
91 : SurfaceReadPixelsSupport::kUnsupported;
92 }
93
onSurfaceSupportsWritePixels(const GrSurface * surface) const94 bool GrDawnCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
95 // We currently support writePixels only to Textures and TextureRenderTargets.
96 return surface->asTexture() != nullptr;
97 }
98
getRenderTargetSampleCount(int requestedCount,const GrBackendFormat & backendFormat) const99 int GrDawnCaps::getRenderTargetSampleCount(int requestedCount,
100 const GrBackendFormat& backendFormat) const {
101 wgpu::TextureFormat dawnFormat;
102 if (!backendFormat.asDawnFormat(&dawnFormat)) {
103 return 0;
104 }
105 return GrDawnFormatIsRenderable(dawnFormat) ? 1 : 0;
106 }
107
maxRenderTargetSampleCount(const GrBackendFormat & format) const108 int GrDawnCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
109 return format.isValid() ? 1 : 0;
110 }
111
onGetDefaultBackendFormat(GrColorType ct) const112 GrBackendFormat GrDawnCaps::onGetDefaultBackendFormat(GrColorType ct) const {
113 wgpu::TextureFormat format;
114 if (!GrColorTypeToDawnFormat(ct, &format)) {
115 return {};
116 }
117 return GrBackendFormat::MakeDawn(format);
118 }
119
getBackendFormatFromCompressionType(SkImage::CompressionType type) const120 GrBackendFormat GrDawnCaps::getBackendFormatFromCompressionType(SkImage::CompressionType type) const
121 {
122 return GrBackendFormat();
123 }
124
onGetReadSwizzle(const GrBackendFormat & format,GrColorType colorType) const125 GrSwizzle GrDawnCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const
126 {
127 return get_swizzle(format, colorType, false);
128 }
129
getWriteSwizzle(const GrBackendFormat & format,GrColorType colorType) const130 GrSwizzle GrDawnCaps::getWriteSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
131 return get_swizzle(format, colorType, true);
132 }
133
computeFormatKey(const GrBackendFormat & format) const134 uint64_t GrDawnCaps::computeFormatKey(const GrBackendFormat& format) const {
135 wgpu::TextureFormat dawnFormat;
136 SkAssertResult(format.asDawnFormat(&dawnFormat));
137
138 // Dawn max enum value should always fit in 32 bits.
139
140 // disabled: no member named 'WGPUTextureFormat_Force32' in namespace 'wgpu'
141 //SkASSERT(dawnFormat <= wgpu::WGPUTextureFormat_Force32);
142 return (uint64_t)dawnFormat;
143 }
144
onAreColorTypeAndFormatCompatible(GrColorType ct,const GrBackendFormat & format) const145 bool GrDawnCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
146 const GrBackendFormat& format) const {
147 return true;
148 }
149
150 // FIXME: taken from GrVkPipelineState; refactor.
get_blend_info_key(const GrPipeline & pipeline)151 static uint32_t get_blend_info_key(const GrPipeline& pipeline) {
152 GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
153
154 static const uint32_t kBlendWriteShift = 1;
155 static const uint32_t kBlendCoeffShift = 5;
156 static_assert(kLast_GrBlendCoeff < (1 << kBlendCoeffShift));
157 static_assert(kFirstAdvancedGrBlendEquation - 1 < 4);
158
159 uint32_t key = blendInfo.fWriteColor;
160 key |= (blendInfo.fSrcBlend << kBlendWriteShift);
161 key |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
162 key |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
163
164 return key;
165 }
166
makeDesc(GrRenderTarget * rt,const GrProgramInfo & programInfo,ProgramDescOverrideFlags overrideFlags) const167 GrProgramDesc GrDawnCaps::makeDesc(GrRenderTarget* rt,
168 const GrProgramInfo& programInfo,
169 ProgramDescOverrideFlags overrideFlags) const {
170 SkASSERT(overrideFlags == ProgramDescOverrideFlags::kNone);
171 GrProgramDesc desc;
172 GrProgramDesc::Build(&desc, programInfo, *this);
173
174 wgpu::TextureFormat format;
175 if (!programInfo.backendFormat().asDawnFormat(&format)) {
176 desc.reset();
177 SkASSERT(!desc.isValid());
178 return desc;
179 }
180
181 GrProcessorKeyBuilder b(desc.key());
182 GrStencilSettings stencil = programInfo.nonGLStencilSettings();
183 stencil.genKey(&b, true);
184
185 // TODO: remove this reliance on the renderTarget
186 bool hasDepthStencil = rt->getStencilAttachment() != nullptr;
187
188 b.add32(static_cast<uint32_t>(format));
189 b.add32(static_cast<int32_t>(hasDepthStencil));
190 b.add32(get_blend_info_key(programInfo.pipeline()));
191 b.add32(programInfo.primitiveTypeKey());
192
193 b.flush();
194 return desc;
195 }
196
197 #if GR_TEST_UTILS
getTestingCombinations() const198 std::vector<GrCaps::TestFormatColorTypeCombination> GrDawnCaps::getTestingCombinations() const {
199 std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
200 { GrColorType::kAlpha_8, GrBackendFormat::MakeDawn(wgpu::TextureFormat::R8Unorm) },
201 { GrColorType::kRGBA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::RGBA8Unorm) },
202 { GrColorType::kRGBA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::BGRA8Unorm) },
203 { GrColorType::kRGB_888x, GrBackendFormat::MakeDawn(wgpu::TextureFormat::RGBA8Unorm) },
204 { GrColorType::kRGB_888x, GrBackendFormat::MakeDawn(wgpu::TextureFormat::BGRA8Unorm) },
205 { GrColorType::kBGRA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::BGRA8Unorm) },
206 { GrColorType::kBGRA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::RGBA8Unorm) },
207 };
208
209 #ifdef SK_DEBUG
210 for (const GrCaps::TestFormatColorTypeCombination& combo : combos) {
211 SkASSERT(this->onAreColorTypeAndFormatCompatible(combo.fColorType, combo.fFormat));
212 }
213 #endif
214 return combos;
215 }
216 #endif
217