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/ganesh/dawn/GrDawnCaps.h"
9
10 #include "src/gpu/KeyBuilder.h"
11 #include "src/gpu/ganesh/GrProgramDesc.h"
12 #include "src/gpu/ganesh/GrProgramInfo.h"
13 #include "src/gpu/ganesh/GrRenderTarget.h"
14 #include "src/gpu/ganesh/GrStencilSettings.h"
15 #include "src/gpu/ganesh/TestFormatColorTypeCombination.h"
16
GrDawnCaps(const GrContextOptions & contextOptions)17 GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) {
18 fMipmapSupport = true;
19 fAnisoSupport = true;
20 fBufferMapThreshold = SK_MaxS32; // FIXME: get this from Dawn?
21 fShaderCaps = std::make_unique<GrShaderCaps>();
22 fMaxTextureSize = fMaxRenderTargetSize = 8192; // FIXME
23 fMaxVertexAttributes = 16; // FIXME
24 fClampToBorderSupport = false;
25 fPerformPartialClearsAsDraws = true;
26 fDynamicStateArrayGeometryProcessorTextureSupport = true;
27 fTwoSidedStencilRefsAndMasksMustMatch = true;
28
29 // WebGPU zero-initializes resources. https://www.w3.org/TR/webgpu/#security-uninitialized
30 fBuffersAreInitiallyZero = true;
31
32 fShaderCaps->fFlatInterpolationSupport = true;
33 fShaderCaps->fIntegerSupport = true;
34 // FIXME: each fragment sampler takes two binding slots in Dawn (sampler + texture). Limit to
35 // 6 * 2 = 12, since kMaxBindingsPerGroup is 16 in Dawn, and we need to keep a few for
36 // non-texture bindings. Eventually, we may be able to increase kMaxBindingsPerGroup in Dawn.
37 fShaderCaps->fMaxFragmentSamplers = 6;
38 fShaderCaps->fShaderDerivativeSupport = true;
39 fShaderCaps->fExplicitTextureLodSupport = true;
40
41 // We haven't yet implemented GrGpu::transferFromBufferToBuffer for Dawn but GrDawnBuffer uses
42 // transfers to implement buffer mapping and updates and transfers must be 4 byte aligned.
43 fTransferFromBufferToBufferAlignment = 4;
44 // Buffer updates are sometimes implemented through transfers in GrDawnBuffer.
45 fBufferUpdateDataPreserveAlignment = 4;
46
47 this->finishInitialization(contextOptions);
48 }
49
isFormatSRGB(const GrBackendFormat & format) const50 bool GrDawnCaps::isFormatSRGB(const GrBackendFormat& format) const {
51 return false;
52 }
53
isFormatTexturable(const GrBackendFormat & format,GrTextureType) const54 bool GrDawnCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const {
55 // Currently, all the formats in GrDawnFormatToPixelConfig are texturable.
56 wgpu::TextureFormat dawnFormat;
57 return format.asDawnFormat(&dawnFormat);
58 }
59
get_swizzle(const GrBackendFormat & format,GrColorType colorType,bool forOutput)60 static skgpu::Swizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
61 bool forOutput) {
62 switch (colorType) {
63 case GrColorType::kAlpha_8: // fall through
64 case GrColorType::kAlpha_F16:
65 if (forOutput) {
66 return skgpu::Swizzle("a000");
67 } else {
68 return skgpu::Swizzle("000r");
69 }
70 case GrColorType::kGray_8:
71 if (!forOutput) {
72 return skgpu::Swizzle::RRRA();
73 }
74 break;
75 case GrColorType::kRGB_888x:
76 if (!forOutput) {
77 return skgpu::Swizzle::RGB1();
78 }
79 break;
80 default:
81 return skgpu::Swizzle::RGBA();
82 }
83 return skgpu::Swizzle::RGBA();
84 }
85
isFormatRenderable(const GrBackendFormat & format,int sampleCount) const86 bool GrDawnCaps::isFormatRenderable(const GrBackendFormat& format,
87 int sampleCount) const {
88 wgpu::TextureFormat dawnFormat;
89 if (!format.isValid() || sampleCount > 1 || !format.asDawnFormat(&dawnFormat)) {
90 return false;
91 }
92
93 return GrDawnFormatIsRenderable(dawnFormat);
94 }
95
isFormatAsColorTypeRenderable(GrColorType ct,const GrBackendFormat & format,int sampleCount) const96 bool GrDawnCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
97 int sampleCount) const {
98 return isFormatRenderable(format, sampleCount);
99 }
100
surfaceSupportsReadPixels(const GrSurface * surface) const101 GrCaps::SurfaceReadPixelsSupport GrDawnCaps::surfaceSupportsReadPixels(
102 const GrSurface* surface) const {
103 // We currently support readbacks only from Textures and TextureRenderTargets.
104 return surface->asTexture() ? SurfaceReadPixelsSupport::kSupported
105 : SurfaceReadPixelsSupport::kUnsupported;
106 }
107
onSurfaceSupportsWritePixels(const GrSurface * surface) const108 bool GrDawnCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
109 // We currently support writePixels only to Textures and TextureRenderTargets.
110 return surface->asTexture() != nullptr;
111 }
112
getRenderTargetSampleCount(int requestedCount,const GrBackendFormat & backendFormat) const113 int GrDawnCaps::getRenderTargetSampleCount(int requestedCount,
114 const GrBackendFormat& backendFormat) const {
115 wgpu::TextureFormat dawnFormat;
116 if (!backendFormat.asDawnFormat(&dawnFormat)) {
117 return 0;
118 }
119 return GrDawnFormatIsRenderable(dawnFormat) ? 1 : 0;
120 }
121
maxRenderTargetSampleCount(const GrBackendFormat & format) const122 int GrDawnCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
123 return format.isValid() ? 1 : 0;
124 }
125
onGetDefaultBackendFormat(GrColorType ct) const126 GrBackendFormat GrDawnCaps::onGetDefaultBackendFormat(GrColorType ct) const {
127 wgpu::TextureFormat format;
128 if (!GrColorTypeToDawnFormat(ct, &format)) {
129 return {};
130 }
131 return GrBackendFormat::MakeDawn(format);
132 }
133
getBackendFormatFromCompressionType(SkImage::CompressionType type) const134 GrBackendFormat GrDawnCaps::getBackendFormatFromCompressionType(SkImage::CompressionType type) const
135 {
136 return GrBackendFormat();
137 }
138
onGetReadSwizzle(const GrBackendFormat & format,GrColorType colorType) const139 skgpu::Swizzle GrDawnCaps::onGetReadSwizzle(const GrBackendFormat& format,
140 GrColorType colorType) const {
141 return get_swizzle(format, colorType, false);
142 }
143
getWriteSwizzle(const GrBackendFormat & format,GrColorType colorType) const144 skgpu::Swizzle GrDawnCaps::getWriteSwizzle(const GrBackendFormat& format,
145 GrColorType colorType) const {
146 return get_swizzle(format, colorType, true);
147 }
148
computeFormatKey(const GrBackendFormat & format) const149 uint64_t GrDawnCaps::computeFormatKey(const GrBackendFormat& format) const {
150 wgpu::TextureFormat dawnFormat;
151 SkAssertResult(format.asDawnFormat(&dawnFormat));
152
153 // Dawn max enum value should always fit in 32 bits.
154
155 // disabled: no member named 'WGPUTextureFormat_Force32' in namespace 'wgpu'
156 //SkASSERT(dawnFormat <= wgpu::WGPUTextureFormat_Force32);
157 return (uint64_t)dawnFormat;
158 }
159
onAreColorTypeAndFormatCompatible(GrColorType ct,const GrBackendFormat & format) const160 bool GrDawnCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
161 const GrBackendFormat& format) const {
162 return true;
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 skgpu::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
168
169 static const uint32_t kBlendWriteShift = 1;
170 static const uint32_t kBlendCoeffShift = 5;
171 static_assert((int)skgpu::BlendCoeff::kLast < (1 << kBlendCoeffShift));
172 static_assert((int)skgpu::BlendEquation::kFirstAdvanced - 1 < 4);
173
174 uint32_t key = blendInfo.fWritesColor;
175 key |= ((int)blendInfo.fSrcBlend << kBlendWriteShift);
176 key |= ((int)blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift));
177 key |= ((int)blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift));
178
179 return key;
180 }
181
makeDesc(GrRenderTarget * rt,const GrProgramInfo & programInfo,ProgramDescOverrideFlags overrideFlags) const182 GrProgramDesc GrDawnCaps::makeDesc(GrRenderTarget* rt,
183 const GrProgramInfo& programInfo,
184 ProgramDescOverrideFlags overrideFlags) const {
185 SkASSERT(overrideFlags == ProgramDescOverrideFlags::kNone);
186 GrProgramDesc desc;
187 GrProgramDesc::Build(&desc, programInfo, *this);
188
189 wgpu::TextureFormat format;
190 if (!programInfo.backendFormat().asDawnFormat(&format)) {
191 desc.reset();
192 SkASSERT(!desc.isValid());
193 return desc;
194 }
195
196 skgpu::KeyBuilder b(desc.key());
197 GrStencilSettings stencil = programInfo.nonGLStencilSettings();
198 stencil.genKey(&b, true);
199
200 // TODO: remove this reliance on the renderTarget
201 bool hasDepthStencil = rt->getStencilAttachment() != nullptr;
202
203 b.add32(static_cast<uint32_t>(format));
204 b.add32(static_cast<int32_t>(hasDepthStencil));
205 b.add32(get_blend_info_key(programInfo.pipeline()));
206 b.add32(programInfo.primitiveTypeKey());
207
208 b.flush();
209 return desc;
210 }
211
212 #if GR_TEST_UTILS
getTestingCombinations() const213 std::vector<GrTest::TestFormatColorTypeCombination> GrDawnCaps::getTestingCombinations() const {
214 std::vector<GrTest::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 (const GrTest::TestFormatColorTypeCombination& combo : combos) {
226 SkASSERT(this->onAreColorTypeAndFormatCompatible(combo.fColorType, combo.fFormat));
227 }
228 #endif
229 return combos;
230 }
231 #endif
232