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