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/GrRenderTargetPriv.h"
14 #include "src/gpu/GrStencilSettings.h"
15 
GrDawnCaps(const GrContextOptions & contextOptions)16 GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) {
17     fMipMapSupport = false;  // FIXME: implement onRegenerateMipMapLevels in GrDawnGpu.
18     fBufferMapThreshold = SK_MaxS32;  // FIXME: get this from Dawn?
19     fShaderCaps.reset(new GrShaderCaps(contextOptions));
20     fMaxTextureSize = fMaxRenderTargetSize = 8192; // FIXME
21     fMaxVertexAttributes = 16; // FIXME
22     fClampToBorderSupport = false;
23     fPerformPartialClearsAsDraws = true;
24     fDynamicStateArrayGeometryProcessorTextureSupport = true;
25 
26     fShaderCaps->fFlatInterpolationSupport = true;
27     fShaderCaps->fIntegerSupport = true;
28     // FIXME: each fragment sampler takes two binding slots in Dawn (sampler + texture). Limit to
29     // 6 * 2 = 12, since kMaxBindingsPerGroup is 16 in Dawn, and we need to keep a few for
30     // non-texture bindings. Eventually, we may be able to increase kMaxBindingsPerGroup in Dawn.
31     fShaderCaps->fMaxFragmentSamplers = 6;
32     fShaderCaps->fShaderDerivativeSupport = true;
33 
34     this->finishInitialization(contextOptions);
35 }
36 
isFormatSRGB(const GrBackendFormat & format) const37 bool GrDawnCaps::isFormatSRGB(const GrBackendFormat& format) const {
38     return false;
39 }
40 
compressionType(const GrBackendFormat & format) const41 SkImage::CompressionType GrDawnCaps::compressionType(const GrBackendFormat& format) const {
42     return SkImage::CompressionType::kNone;
43 }
44 
isFormatTexturable(const GrBackendFormat & format) const45 bool GrDawnCaps::isFormatTexturable(const GrBackendFormat& format) const {
46     // Currently, all the formats in GrDawnFormatToPixelConfig are texturable.
47     wgpu::TextureFormat dawnFormat;
48     return format.asDawnFormat(&dawnFormat);
49 }
50 
get_swizzle(const GrBackendFormat & format,GrColorType colorType,bool forOutput)51 static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
52                              bool forOutput) {
53     switch (colorType) {
54         case GrColorType::kAlpha_8: // fall through
55         case GrColorType::kAlpha_F16:
56             if (forOutput) {
57                 return GrSwizzle::AAAA();
58             } else {
59                 return GrSwizzle::RRRR();
60             }
61         case GrColorType::kGray_8:
62             if (!forOutput) {
63                 return GrSwizzle::RRRA();
64             }
65             break;
66         case GrColorType::kRGB_888x:
67             if (!forOutput) {
68                 return GrSwizzle::RGB1();
69             }
70         default:
71             return GrSwizzle::RGBA();
72     }
73     return GrSwizzle::RGBA();
74 }
75 
isFormatRenderable(const GrBackendFormat & format,int sampleCount) const76 bool GrDawnCaps::isFormatRenderable(const GrBackendFormat& format,
77                                     int sampleCount) const {
78     wgpu::TextureFormat dawnFormat;
79     if (!format.isValid() || sampleCount > 1 || !format.asDawnFormat(&dawnFormat)) {
80         return false;
81     }
82 
83     return GrDawnFormatIsRenderable(dawnFormat);
84 }
85 
isFormatAsColorTypeRenderable(GrColorType ct,const GrBackendFormat & format,int sampleCount) const86 bool GrDawnCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
87                                                int sampleCount) const {
88     return isFormatRenderable(format, sampleCount);
89 }
90 
bytesPerPixel(const GrBackendFormat & backendFormat) const91 size_t GrDawnCaps::bytesPerPixel(const GrBackendFormat& backendFormat) const {
92     wgpu::TextureFormat dawnFormat;
93     if (!backendFormat.asDawnFormat(&dawnFormat)) {
94         return 0;
95     }
96     return GrDawnBytesPerPixel(dawnFormat);
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 
getReadSwizzle(const GrBackendFormat & format,GrColorType colorType) const125 GrSwizzle GrDawnCaps::getReadSwizzle(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 
getYUVAColorTypeFromBackendFormat(const GrBackendFormat & backendFormat,bool isAlphaChannel) const150 GrColorType GrDawnCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& backendFormat,
151                                                           bool isAlphaChannel) const {
152     wgpu::TextureFormat textureFormat;
153     if (!backendFormat.asDawnFormat(&textureFormat)) {
154         return GrColorType::kUnknown;
155     }
156     switch (textureFormat) {
157         case wgpu::TextureFormat::R8Unorm:     return isAlphaChannel ? GrColorType::kAlpha_8
158                                                                      : GrColorType::kGray_8;
159         case wgpu::TextureFormat::RGBA8Unorm:  return GrColorType::kRGBA_8888;
160         case wgpu::TextureFormat::BGRA8Unorm:  return GrColorType::kBGRA_8888;
161         default:                               return GrColorType::kUnknown;
162     }
163 }
164 
165 // FIXME: taken from GrVkPipelineState; refactor.
get_blend_info_key(const GrPipeline & pipeline)166 static uint32_t get_blend_info_key(const GrPipeline& pipeline) {
167     GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
168 
169     static const uint32_t kBlendWriteShift = 1;
170     static const uint32_t kBlendCoeffShift = 5;
171     static_assert(kLast_GrBlendCoeff < (1 << kBlendCoeffShift));
172     static_assert(kFirstAdvancedGrBlendEquation - 1 < 4);
173 
174     uint32_t key = blendInfo.fWriteColor;
175     key |= (blendInfo.fSrcBlend << kBlendWriteShift);
176     key |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
177     key |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
178 
179     return key;
180 }
181 
makeDesc(const GrRenderTarget * rt,const GrProgramInfo & programInfo) const182 GrProgramDesc GrDawnCaps::makeDesc(const GrRenderTarget* rt,
183                                    const GrProgramInfo& programInfo) const {
184     GrProgramDesc desc;
185     if (!GrProgramDesc::Build(&desc, rt, programInfo, *this)) {
186         SkASSERT(!desc.isValid());
187         return desc;
188     }
189 
190     wgpu::TextureFormat format;
191     if (!programInfo.backendFormat().asDawnFormat(&format)) {
192         desc.key().reset();
193         SkASSERT(!desc.isValid());
194         return desc;
195     }
196 
197     GrProcessorKeyBuilder b(&desc.key());
198 
199     GrStencilSettings stencil = programInfo.nonGLStencilSettings();
200     stencil.genKey(&b);
201 
202     // TODO: remove this reliance on the renderTarget
203     bool hasDepthStencil = rt->renderTargetPriv().getStencilAttachment() != nullptr;
204 
205     b.add32(static_cast<uint32_t>(format));
206     b.add32(static_cast<int32_t>(hasDepthStencil));
207     b.add32(get_blend_info_key(programInfo.pipeline()));
208     b.add32(programInfo.primitiveTypeKey());
209     return desc;
210 }
211 
212 #if GR_TEST_UTILS
getTestingCombinations() const213 std::vector<GrCaps::TestFormatColorTypeCombination> GrDawnCaps::getTestingCombinations() const {
214     std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
215         { GrColorType::kAlpha_8,   GrBackendFormat::MakeDawn(wgpu::TextureFormat::R8Unorm)    },
216         { GrColorType::kRGBA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::RGBA8Unorm) },
217         { GrColorType::kRGBA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::BGRA8Unorm) },
218         { GrColorType::kRGB_888x,  GrBackendFormat::MakeDawn(wgpu::TextureFormat::RGBA8Unorm) },
219         { GrColorType::kRGB_888x,  GrBackendFormat::MakeDawn(wgpu::TextureFormat::BGRA8Unorm) },
220         { GrColorType::kBGRA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::BGRA8Unorm) },
221         { GrColorType::kBGRA_8888, GrBackendFormat::MakeDawn(wgpu::TextureFormat::RGBA8Unorm) },
222     };
223 
224 #ifdef SK_DEBUG
225     for (auto combo : combos) {
226         SkASSERT(this->onAreColorTypeAndFormatCompatible(combo.fColorType, combo.fFormat));
227     }
228 #endif
229     return combos;
230 }
231 #endif
232