1 //
2 // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "libANGLE/renderer/wgpu/wgpu_utils.h"
8
9 #include "libANGLE/renderer/renderer_utils.h"
10 #include "libANGLE/renderer/wgpu/ContextWgpu.h"
11 #include "libANGLE/renderer/wgpu/DisplayWgpu.h"
12 #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h"
13
14 namespace rx
15 {
16
17 namespace webgpu
18 {
GetDisplay(const gl::Context * context)19 DisplayWgpu *GetDisplay(const gl::Context *context)
20 {
21 ContextWgpu *contextWgpu = GetImpl(context);
22 return contextWgpu->getDisplay();
23 }
24
GetDevice(const gl::Context * context)25 wgpu::Device GetDevice(const gl::Context *context)
26 {
27 DisplayWgpu *display = GetDisplay(context);
28 return display->getDevice();
29 }
30
GetInstance(const gl::Context * context)31 wgpu::Instance GetInstance(const gl::Context *context)
32 {
33 DisplayWgpu *display = GetDisplay(context);
34 return display->getInstance();
35 }
36
CreateNewClearColorAttachment(wgpu::Color clearValue,uint32_t depthSlice,wgpu::TextureView textureView)37 wgpu::RenderPassColorAttachment CreateNewClearColorAttachment(wgpu::Color clearValue,
38 uint32_t depthSlice,
39 wgpu::TextureView textureView)
40 {
41 wgpu::RenderPassColorAttachment colorAttachment;
42 colorAttachment.view = textureView;
43 colorAttachment.depthSlice = depthSlice;
44 colorAttachment.loadOp = wgpu::LoadOp::Clear;
45 colorAttachment.storeOp = wgpu::StoreOp::Store;
46 colorAttachment.clearValue = clearValue;
47
48 return colorAttachment;
49 }
50
CreateNewDepthStencilAttachment(float depthClearValue,uint32_t stencilClearValue,wgpu::TextureView textureView,bool hasDepthValue,bool hasStencilValue)51 wgpu::RenderPassDepthStencilAttachment CreateNewDepthStencilAttachment(
52 float depthClearValue,
53 uint32_t stencilClearValue,
54 wgpu::TextureView textureView,
55 bool hasDepthValue,
56 bool hasStencilValue)
57 {
58 wgpu::RenderPassDepthStencilAttachment depthStencilAttachment;
59 depthStencilAttachment.view = textureView;
60 // WebGPU requires that depth/stencil attachments have a load op if the correlated ReadOnly
61 // value is set to false, so we make sure to set the value here to to support cases where only a
62 // depth or stencil mask is set.
63 depthStencilAttachment.depthReadOnly = !hasDepthValue;
64 depthStencilAttachment.stencilReadOnly = !hasStencilValue;
65 if (hasDepthValue)
66 {
67 depthStencilAttachment.depthLoadOp = wgpu::LoadOp::Clear;
68 depthStencilAttachment.depthStoreOp = wgpu::StoreOp::Store;
69 depthStencilAttachment.depthClearValue = depthClearValue;
70 }
71 if (hasStencilValue)
72 {
73 depthStencilAttachment.stencilLoadOp = wgpu::LoadOp::Clear;
74 depthStencilAttachment.stencilStoreOp = wgpu::StoreOp::Store;
75 depthStencilAttachment.stencilClearValue = stencilClearValue;
76 }
77
78 return depthStencilAttachment;
79 }
80
IsWgpuError(wgpu::WaitStatus waitStatus)81 bool IsWgpuError(wgpu::WaitStatus waitStatus)
82 {
83 return waitStatus != wgpu::WaitStatus::Success;
84 }
85
IsWgpuError(wgpu::MapAsyncStatus mapAsyncStatus)86 bool IsWgpuError(wgpu::MapAsyncStatus mapAsyncStatus)
87 {
88 return mapAsyncStatus != wgpu::MapAsyncStatus::Success;
89 }
90
ClearValuesArray()91 ClearValuesArray::ClearValuesArray() : mValues{}, mEnabled{} {}
92 ClearValuesArray::~ClearValuesArray() = default;
93
94 ClearValuesArray::ClearValuesArray(const ClearValuesArray &other) = default;
95 ClearValuesArray &ClearValuesArray::operator=(const ClearValuesArray &rhs) = default;
96
store(uint32_t index,const ClearValues & clearValues)97 void ClearValuesArray::store(uint32_t index, const ClearValues &clearValues)
98 {
99 mValues[index] = clearValues;
100 mEnabled.set(index);
101 }
102
getColorMask() const103 gl::DrawBufferMask ClearValuesArray::getColorMask() const
104 {
105 return gl::DrawBufferMask(mEnabled.bits() & kUnpackedColorBuffersMask);
106 }
107
GenerateCaps(const wgpu::Limits & limitsWgpu,gl::Caps * glCaps,gl::TextureCapsMap * glTextureCapsMap,gl::Extensions * glExtensions,gl::Limitations * glLimitations,egl::Caps * eglCaps,egl::DisplayExtensions * eglExtensions,gl::Version * maxSupportedESVersion)108 void GenerateCaps(const wgpu::Limits &limitsWgpu,
109 gl::Caps *glCaps,
110 gl::TextureCapsMap *glTextureCapsMap,
111 gl::Extensions *glExtensions,
112 gl::Limitations *glLimitations,
113 egl::Caps *eglCaps,
114 egl::DisplayExtensions *eglExtensions,
115 gl::Version *maxSupportedESVersion)
116 {
117 // WebGPU does not support separate front/back stencil masks.
118 glLimitations->noSeparateStencilRefsAndMasks = true;
119
120 // OpenGL ES extensions
121 glExtensions->debugMarkerEXT = true;
122 glExtensions->textureUsageANGLE = true;
123 glExtensions->translatedShaderSourceANGLE = true;
124 glExtensions->vertexArrayObjectOES = true;
125 glExtensions->elementIndexUintOES = true;
126
127 glExtensions->textureStorageEXT = true;
128 glExtensions->rgb8Rgba8OES = true;
129
130 // OpenGL ES caps
131 glCaps->maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
132 glCaps->max3DTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension3D);
133 glCaps->max2DTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
134 glCaps->maxArrayTextureLayers = rx::LimitToInt(limitsWgpu.maxTextureArrayLayers);
135 glCaps->maxLODBias = 0.0f;
136 glCaps->maxCubeMapTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
137 glCaps->maxRenderbufferSize = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
138 glCaps->minAliasedPointSize = 1.0f;
139 glCaps->maxAliasedPointSize = 1.0f;
140 glCaps->minAliasedLineWidth = 1.0f;
141 glCaps->maxAliasedLineWidth = 1.0f;
142
143 // "descriptor.sampleCount must be either 1 or 4."
144 constexpr uint32_t kMaxSampleCount = 4;
145
146 glCaps->maxDrawBuffers = rx::LimitToInt(limitsWgpu.maxColorAttachments);
147 glCaps->maxFramebufferWidth = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
148 glCaps->maxFramebufferHeight = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
149 glCaps->maxFramebufferSamples = kMaxSampleCount;
150 glCaps->maxColorAttachments = rx::LimitToInt(limitsWgpu.maxColorAttachments);
151 glCaps->maxViewportWidth = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
152 glCaps->maxViewportHeight = glCaps->maxViewportWidth;
153 glCaps->maxSampleMaskWords = 1;
154 glCaps->maxColorTextureSamples = kMaxSampleCount;
155 glCaps->maxDepthTextureSamples = kMaxSampleCount;
156 glCaps->maxIntegerSamples = kMaxSampleCount;
157 glCaps->maxServerWaitTimeout = 0;
158
159 glCaps->maxVertexAttribRelativeOffset = (1u << kAttributeOffsetMaxBits) - 1;
160 glCaps->maxVertexAttribBindings =
161 rx::LimitToInt(std::min(limitsWgpu.maxVertexBuffers, limitsWgpu.maxVertexAttributes));
162 glCaps->maxVertexAttribStride =
163 rx::LimitToInt(std::min(limitsWgpu.maxVertexBufferArrayStride,
164 static_cast<uint32_t>(std::numeric_limits<uint16_t>::max())));
165 glCaps->maxElementsIndices = std::numeric_limits<GLint>::max();
166 glCaps->maxElementsVertices = std::numeric_limits<GLint>::max();
167 glCaps->vertexHighpFloat.setIEEEFloat();
168 glCaps->vertexMediumpFloat.setIEEEHalfFloat();
169 glCaps->vertexLowpFloat.setIEEEHalfFloat();
170 glCaps->fragmentHighpFloat.setIEEEFloat();
171 glCaps->fragmentMediumpFloat.setIEEEHalfFloat();
172 glCaps->fragmentLowpFloat.setIEEEHalfFloat();
173 glCaps->vertexHighpInt.setTwosComplementInt(32);
174 glCaps->vertexMediumpInt.setTwosComplementInt(16);
175 glCaps->vertexLowpInt.setTwosComplementInt(16);
176 glCaps->fragmentHighpInt.setTwosComplementInt(32);
177 glCaps->fragmentMediumpInt.setTwosComplementInt(16);
178 glCaps->fragmentLowpInt.setTwosComplementInt(16);
179
180 // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size
181 // currently), on AMD the maxUniformBufferRange is near uint32_t max.
182 GLuint maxUniformBlockSize = static_cast<GLuint>(
183 std::min(static_cast<uint64_t>(0x10000), limitsWgpu.maxUniformBufferBindingSize));
184
185 const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * 4);
186 const GLuint maxUniformComponents = maxUniformVectors * 4;
187
188 const int32_t maxPerStageUniformBuffers = rx::LimitToInt(
189 limitsWgpu.maxUniformBuffersPerShaderStage - kReservedPerStageDefaultUniformSlotCount);
190
191 // There is no additional limit to the combined number of components. We can have up to a
192 // maximum number of uniform buffers, each having the maximum number of components. Note that
193 // this limit includes both components in and out of uniform buffers.
194 //
195 // This value is limited to INT_MAX to avoid overflow when queried from glGetIntegerv().
196 const uint64_t maxCombinedUniformComponents =
197 std::min<uint64_t>(static_cast<uint64_t>(maxPerStageUniformBuffers +
198 kReservedPerStageDefaultUniformSlotCount) *
199 maxUniformComponents,
200 std::numeric_limits<GLint>::max());
201
202 for (gl::ShaderType shaderType : gl::AllShaderTypes())
203 {
204 glCaps->maxShaderUniformBlocks[shaderType] = maxPerStageUniformBuffers;
205 glCaps->maxShaderTextureImageUnits[shaderType] =
206 rx::LimitToInt(limitsWgpu.maxSamplersPerShaderStage);
207 glCaps->maxShaderStorageBlocks[shaderType] = 0;
208 glCaps->maxShaderUniformComponents[shaderType] = 0;
209 glCaps->maxShaderAtomicCounterBuffers[shaderType] = 0;
210 glCaps->maxShaderAtomicCounters[shaderType] = 0;
211 glCaps->maxShaderImageUniforms[shaderType] = 0;
212 glCaps->maxCombinedShaderUniformComponents[shaderType] = maxCombinedUniformComponents;
213 }
214
215 const GLint maxVaryingComponents = rx::LimitToInt(limitsWgpu.maxInterStageShaderVariables * 4);
216
217 glCaps->maxVertexAttributes = rx::LimitToInt(
218 limitsWgpu.maxVertexBuffers); // WebGPU has maxVertexBuffers and maxVertexAttributes but
219 // since each vertex attribute can use a unique buffer, we
220 // are limited by the total number of vertex buffers
221 glCaps->maxVertexUniformVectors =
222 maxUniformVectors; // Uniforms are implemented using a uniform buffer, so the max number of
223 // uniforms we can support is the max buffer range divided by the size
224 // of a single uniform (4X float).
225 glCaps->maxVertexOutputComponents = maxVaryingComponents;
226
227 glCaps->maxFragmentUniformVectors = maxUniformVectors;
228 glCaps->maxFragmentInputComponents = maxVaryingComponents;
229 glCaps->minProgramTextureGatherOffset = 0;
230 glCaps->maxProgramTextureGatherOffset = 0;
231 glCaps->minProgramTexelOffset = -8;
232 glCaps->maxProgramTexelOffset = 7;
233
234 glCaps->maxComputeWorkGroupCount = {0, 0, 0};
235 glCaps->maxComputeWorkGroupSize = {0, 0, 0};
236 glCaps->maxComputeWorkGroupInvocations = 0;
237 glCaps->maxComputeSharedMemorySize = 0;
238
239 // Only 2 stages (vertex+fragment) are supported.
240 constexpr uint32_t kShaderStageCount = 2;
241
242 glCaps->maxUniformBufferBindings = maxPerStageUniformBuffers * kShaderStageCount;
243 glCaps->maxUniformBlockSize = rx::LimitToInt(limitsWgpu.maxBufferSize);
244 glCaps->uniformBufferOffsetAlignment =
245 rx::LimitToInt(limitsWgpu.minUniformBufferOffsetAlignment);
246 glCaps->maxCombinedUniformBlocks = glCaps->maxUniformBufferBindings;
247 glCaps->maxVaryingComponents = maxVaryingComponents;
248 glCaps->maxVaryingVectors = rx::LimitToInt(limitsWgpu.maxInterStageShaderVariables);
249 glCaps->maxCombinedTextureImageUnits =
250 rx::LimitToInt(limitsWgpu.maxSamplersPerShaderStage * kShaderStageCount);
251 glCaps->maxCombinedShaderOutputResources = 0;
252
253 glCaps->maxUniformLocations = maxUniformVectors;
254 glCaps->maxAtomicCounterBufferBindings = 0;
255 glCaps->maxAtomicCounterBufferSize = 0;
256 glCaps->maxCombinedAtomicCounterBuffers = 0;
257 glCaps->maxCombinedAtomicCounters = 0;
258 glCaps->maxImageUnits = 0;
259 glCaps->maxCombinedImageUniforms = 0;
260 glCaps->maxShaderStorageBufferBindings = 0;
261 glCaps->maxShaderStorageBlockSize = 0;
262 glCaps->maxCombinedShaderStorageBlocks = 0;
263 glCaps->shaderStorageBufferOffsetAlignment = 0;
264
265 glCaps->maxTransformFeedbackInterleavedComponents = 0;
266 glCaps->maxTransformFeedbackSeparateAttributes = 0;
267 glCaps->maxTransformFeedbackSeparateComponents = 0;
268
269 glCaps->lineWidthGranularity = 0.0f;
270 glCaps->minMultisampleLineWidth = 0.0f;
271 glCaps->maxMultisampleLineWidth = 0.0f;
272
273 glCaps->maxTextureBufferSize = 0;
274 glCaps->textureBufferOffsetAlignment = 0;
275
276 glCaps->maxSamples = kMaxSampleCount;
277
278 // Max version
279 *maxSupportedESVersion = gl::Version(3, 2);
280
281 // OpenGL ES texture caps
282 InitMinimumTextureCapsMap(*maxSupportedESVersion, *glExtensions, glTextureCapsMap);
283
284 // EGL caps
285 eglCaps->textureNPOT = true;
286
287 // EGL extensions
288 eglExtensions->createContextRobustness = true;
289 eglExtensions->postSubBuffer = true;
290 eglExtensions->createContext = true;
291 eglExtensions->image = true;
292 eglExtensions->imageBase = true;
293 eglExtensions->glTexture2DImage = true;
294 eglExtensions->glTextureCubemapImage = true;
295 eglExtensions->glTexture3DImage = true;
296 eglExtensions->glRenderbufferImage = true;
297 eglExtensions->getAllProcAddresses = true;
298 eglExtensions->noConfigContext = true;
299 eglExtensions->directComposition = true;
300 eglExtensions->createContextNoError = true;
301 eglExtensions->createContextWebGLCompatibility = true;
302 eglExtensions->createContextBindGeneratesResource = true;
303 eglExtensions->swapBuffersWithDamage = true;
304 eglExtensions->pixelFormatFloat = true;
305 eglExtensions->surfacelessContext = true;
306 eglExtensions->displayTextureShareGroup = true;
307 eglExtensions->displaySemaphoreShareGroup = true;
308 eglExtensions->createContextClientArrays = true;
309 eglExtensions->programCacheControlANGLE = true;
310 eglExtensions->robustResourceInitializationANGLE = true;
311 }
312
IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology)313 bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology)
314 {
315 switch (topology)
316 {
317 case wgpu::PrimitiveTopology::LineStrip:
318 case wgpu::PrimitiveTopology::TriangleStrip:
319 return true;
320
321 default:
322 return false;
323 }
324 }
325
ErrorScope(wgpu::Instance instance,wgpu::Device device,wgpu::ErrorFilter errorType)326 ErrorScope::ErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType)
327 : mInstance(instance), mDevice(device)
328 {
329 mDevice.PushErrorScope(errorType);
330 mActive = true;
331 }
332
~ErrorScope()333 ErrorScope::~ErrorScope()
334 {
335 ANGLE_UNUSED_VARIABLE(PopScope(nullptr, nullptr, nullptr, 0));
336 }
337
PopScope(ContextWgpu * context,const char * file,const char * function,unsigned int line)338 angle::Result ErrorScope::PopScope(ContextWgpu *context,
339 const char *file,
340 const char *function,
341 unsigned int line)
342 {
343 if (!mActive)
344 {
345 return angle::Result::Continue;
346 }
347 mActive = false;
348
349 bool hadError = false;
350 wgpu::Future f = mDevice.PopErrorScope(
351 wgpu::CallbackMode::WaitAnyOnly,
352 [context, file, function, line, &hadError](wgpu::PopErrorScopeStatus status,
353 wgpu::ErrorType type, char const *message) {
354 if (type == wgpu::ErrorType::NoError)
355 {
356 return;
357 }
358
359 if (context)
360 {
361 ASSERT(file);
362 ASSERT(function);
363 context->handleError(GL_INVALID_OPERATION, message, file, function, line);
364 }
365 else
366 {
367 ERR() << "Unhandled WebGPU error: " << message;
368 }
369 hadError = true;
370 });
371 mInstance.WaitAny(f, -1);
372
373 return hadError ? angle::Result::Stop : angle::Result::Continue;
374 }
375
376 } // namespace webgpu
377
378 namespace wgpu_gl
379 {
getLevelIndex(webgpu::LevelIndex levelWgpu,gl::LevelIndex baseLevel)380 gl::LevelIndex getLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel)
381 {
382 return gl::LevelIndex(levelWgpu.get() + baseLevel.get());
383 }
384
getExtents(wgpu::Extent3D wgpuExtent)385 gl::Extents getExtents(wgpu::Extent3D wgpuExtent)
386 {
387 gl::Extents glExtent;
388 glExtent.width = wgpuExtent.width;
389 glExtent.height = wgpuExtent.height;
390 glExtent.depth = wgpuExtent.depthOrArrayLayers;
391 return glExtent;
392 }
393 } // namespace wgpu_gl
394
395 namespace gl_wgpu
396 {
getLevelIndex(gl::LevelIndex levelGl,gl::LevelIndex baseLevel)397 webgpu::LevelIndex getLevelIndex(gl::LevelIndex levelGl, gl::LevelIndex baseLevel)
398 {
399 ASSERT(baseLevel <= levelGl);
400 return webgpu::LevelIndex(levelGl.get() - baseLevel.get());
401 }
402
getExtent3D(const gl::Extents & glExtent)403 wgpu::Extent3D getExtent3D(const gl::Extents &glExtent)
404 {
405 wgpu::Extent3D wgpuExtent;
406 wgpuExtent.width = glExtent.width;
407 wgpuExtent.height = glExtent.height;
408 wgpuExtent.depthOrArrayLayers = glExtent.depth;
409 return wgpuExtent;
410 }
411
GetPrimitiveTopology(gl::PrimitiveMode mode)412 wgpu::PrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode)
413 {
414 switch (mode)
415 {
416 case gl::PrimitiveMode::Points:
417 return wgpu::PrimitiveTopology::PointList;
418 case gl::PrimitiveMode::Lines:
419 return wgpu::PrimitiveTopology::LineList;
420 case gl::PrimitiveMode::LineLoop:
421 return wgpu::PrimitiveTopology::LineStrip; // Emulated
422 case gl::PrimitiveMode::LineStrip:
423 return wgpu::PrimitiveTopology::LineStrip;
424 case gl::PrimitiveMode::Triangles:
425 return wgpu::PrimitiveTopology::TriangleList;
426 case gl::PrimitiveMode::TriangleStrip:
427 return wgpu::PrimitiveTopology::TriangleStrip;
428 case gl::PrimitiveMode::TriangleFan:
429 UNIMPLEMENTED();
430 return wgpu::PrimitiveTopology::TriangleList; // Emulated
431 default:
432 UNREACHABLE();
433 return wgpu::PrimitiveTopology::Undefined;
434 }
435 }
436
GetIndexFormat(gl::DrawElementsType drawElementsType)437 wgpu::IndexFormat GetIndexFormat(gl::DrawElementsType drawElementsType)
438 {
439 switch (drawElementsType)
440 {
441 case gl::DrawElementsType::UnsignedByte:
442 return wgpu::IndexFormat::Uint16; // Emulated
443 case gl::DrawElementsType::UnsignedShort:
444 return wgpu::IndexFormat::Uint16;
445 case gl::DrawElementsType::UnsignedInt:
446 return wgpu::IndexFormat::Uint32;
447
448 default:
449 UNREACHABLE();
450 return wgpu::IndexFormat::Undefined;
451 }
452 }
453
GetFrontFace(GLenum frontFace)454 wgpu::FrontFace GetFrontFace(GLenum frontFace)
455 {
456 switch (frontFace)
457 {
458 case GL_CW:
459 return wgpu::FrontFace::CW;
460 case GL_CCW:
461 return wgpu::FrontFace::CCW;
462
463 default:
464 UNREACHABLE();
465 return wgpu::FrontFace::Undefined;
466 }
467 }
468
GetCullMode(gl::CullFaceMode mode,bool cullFaceEnabled)469 wgpu::CullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled)
470 {
471 if (!cullFaceEnabled)
472 {
473 return wgpu::CullMode::None;
474 }
475
476 switch (mode)
477 {
478 case gl::CullFaceMode::Front:
479 return wgpu::CullMode::Front;
480 case gl::CullFaceMode::Back:
481 return wgpu::CullMode::Back;
482 case gl::CullFaceMode::FrontAndBack:
483 UNIMPLEMENTED();
484 return wgpu::CullMode::None; // Emulated
485 default:
486 UNREACHABLE();
487 return wgpu::CullMode::None;
488 }
489 }
490
GetColorWriteMask(bool r,bool g,bool b,bool a)491 wgpu::ColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a)
492 {
493 return (r ? wgpu::ColorWriteMask::Red : wgpu::ColorWriteMask::None) |
494 (g ? wgpu::ColorWriteMask::Green : wgpu::ColorWriteMask::None) |
495 (b ? wgpu::ColorWriteMask::Blue : wgpu::ColorWriteMask::None) |
496 (a ? wgpu::ColorWriteMask::Alpha : wgpu::ColorWriteMask::None);
497 }
498
GetBlendFactor(gl::BlendFactorType blendFactor)499 wgpu::BlendFactor GetBlendFactor(gl::BlendFactorType blendFactor)
500 {
501 switch (blendFactor)
502 {
503 case gl::BlendFactorType::Zero:
504 return wgpu::BlendFactor::Zero;
505
506 case gl::BlendFactorType::One:
507 return wgpu::BlendFactor::One;
508
509 case gl::BlendFactorType::SrcColor:
510 return wgpu::BlendFactor::Src;
511
512 case gl::BlendFactorType::OneMinusSrcColor:
513 return wgpu::BlendFactor::OneMinusSrc;
514
515 case gl::BlendFactorType::SrcAlpha:
516 return wgpu::BlendFactor::SrcAlpha;
517
518 case gl::BlendFactorType::OneMinusSrcAlpha:
519 return wgpu::BlendFactor::OneMinusSrcAlpha;
520
521 case gl::BlendFactorType::DstAlpha:
522 return wgpu::BlendFactor::DstAlpha;
523
524 case gl::BlendFactorType::OneMinusDstAlpha:
525 return wgpu::BlendFactor::OneMinusDstAlpha;
526
527 case gl::BlendFactorType::DstColor:
528 return wgpu::BlendFactor::Dst;
529
530 case gl::BlendFactorType::OneMinusDstColor:
531 return wgpu::BlendFactor::OneMinusDst;
532
533 case gl::BlendFactorType::SrcAlphaSaturate:
534 return wgpu::BlendFactor::SrcAlphaSaturated;
535
536 case gl::BlendFactorType::ConstantColor:
537 return wgpu::BlendFactor::Constant;
538
539 case gl::BlendFactorType::OneMinusConstantColor:
540 return wgpu::BlendFactor::OneMinusConstant;
541
542 case gl::BlendFactorType::ConstantAlpha:
543 UNIMPLEMENTED();
544 return wgpu::BlendFactor::Undefined;
545
546 case gl::BlendFactorType::OneMinusConstantAlpha:
547 UNIMPLEMENTED();
548 return wgpu::BlendFactor::Undefined;
549
550 case gl::BlendFactorType::Src1Alpha:
551 return wgpu::BlendFactor::Src1Alpha;
552
553 case gl::BlendFactorType::Src1Color:
554 return wgpu::BlendFactor::Src1;
555
556 case gl::BlendFactorType::OneMinusSrc1Color:
557 return wgpu::BlendFactor::OneMinusSrc1;
558
559 case gl::BlendFactorType::OneMinusSrc1Alpha:
560 return wgpu::BlendFactor::OneMinusSrc1Alpha;
561
562 default:
563 UNREACHABLE();
564 return wgpu::BlendFactor::Undefined;
565 }
566 }
567
GetBlendEquation(gl::BlendEquationType blendEquation)568 wgpu::BlendOperation GetBlendEquation(gl::BlendEquationType blendEquation)
569 {
570 switch (blendEquation)
571 {
572 case gl::BlendEquationType::Add:
573 return wgpu::BlendOperation::Add;
574
575 case gl::BlendEquationType::Min:
576 return wgpu::BlendOperation::Min;
577
578 case gl::BlendEquationType::Max:
579 return wgpu::BlendOperation::Max;
580
581 case gl::BlendEquationType::Subtract:
582 return wgpu::BlendOperation::Subtract;
583
584 case gl::BlendEquationType::ReverseSubtract:
585 return wgpu::BlendOperation::ReverseSubtract;
586
587 case gl::BlendEquationType::Multiply:
588 case gl::BlendEquationType::Screen:
589 case gl::BlendEquationType::Overlay:
590 case gl::BlendEquationType::Darken:
591 case gl::BlendEquationType::Lighten:
592 case gl::BlendEquationType::Colordodge:
593 case gl::BlendEquationType::Colorburn:
594 case gl::BlendEquationType::Hardlight:
595 case gl::BlendEquationType::Softlight:
596 case gl::BlendEquationType::Unused2:
597 case gl::BlendEquationType::Difference:
598 case gl::BlendEquationType::Unused3:
599 case gl::BlendEquationType::Exclusion:
600 case gl::BlendEquationType::HslHue:
601 case gl::BlendEquationType::HslSaturation:
602 case gl::BlendEquationType::HslColor:
603 case gl::BlendEquationType::HslLuminosity:
604 // EXT_blend_equation_advanced
605 UNIMPLEMENTED();
606 return wgpu::BlendOperation::Undefined;
607
608 default:
609 UNREACHABLE();
610 return wgpu::BlendOperation::Undefined;
611 }
612 }
613
getWgpuTextureDimension(gl::TextureType glTextureType)614 wgpu::TextureDimension getWgpuTextureDimension(gl::TextureType glTextureType)
615 {
616 wgpu::TextureDimension dimension = {};
617 switch (glTextureType)
618 {
619 case gl::TextureType::_2D:
620 case gl::TextureType::_2DMultisample:
621 case gl::TextureType::Rectangle:
622 case gl::TextureType::External:
623 case gl::TextureType::Buffer:
624 dimension = wgpu::TextureDimension::e2D;
625 break;
626 case gl::TextureType::_2DArray:
627 case gl::TextureType::_2DMultisampleArray:
628 case gl::TextureType::_3D:
629 case gl::TextureType::CubeMap:
630 case gl::TextureType::CubeMapArray:
631 case gl::TextureType::VideoImage:
632 dimension = wgpu::TextureDimension::e3D;
633 break;
634 default:
635 break;
636 }
637 return dimension;
638 }
639
GetCompareFunc(const GLenum glCompareFunc,bool testEnabled)640 wgpu::CompareFunction GetCompareFunc(const GLenum glCompareFunc, bool testEnabled)
641 {
642 if (!testEnabled)
643 {
644 return wgpu::CompareFunction::Always;
645 }
646
647 switch (glCompareFunc)
648 {
649 case GL_NEVER:
650 return wgpu::CompareFunction::Never;
651 case GL_LESS:
652 return wgpu::CompareFunction::Less;
653 case GL_EQUAL:
654 return wgpu::CompareFunction::Equal;
655 case GL_LEQUAL:
656 return wgpu::CompareFunction::LessEqual;
657 case GL_GREATER:
658 return wgpu::CompareFunction::Greater;
659 case GL_NOTEQUAL:
660 return wgpu::CompareFunction::NotEqual;
661 case GL_GEQUAL:
662 return wgpu::CompareFunction::GreaterEqual;
663 case GL_ALWAYS:
664 return wgpu::CompareFunction::Always;
665 default:
666 UNREACHABLE();
667 return wgpu::CompareFunction::Always;
668 }
669 }
670
getStencilOp(const GLenum glStencilOp)671 wgpu::StencilOperation getStencilOp(const GLenum glStencilOp)
672 {
673 switch (glStencilOp)
674 {
675 case GL_KEEP:
676 return wgpu::StencilOperation::Keep;
677 case GL_ZERO:
678 return wgpu::StencilOperation::Zero;
679 case GL_REPLACE:
680 return wgpu::StencilOperation::Replace;
681 case GL_INCR:
682 return wgpu::StencilOperation::IncrementClamp;
683 case GL_DECR:
684 return wgpu::StencilOperation::DecrementClamp;
685 case GL_INCR_WRAP:
686 return wgpu::StencilOperation::IncrementWrap;
687 case GL_DECR_WRAP:
688 return wgpu::StencilOperation::DecrementWrap;
689 case GL_INVERT:
690 return wgpu::StencilOperation::Invert;
691 default:
692 UNREACHABLE();
693 return wgpu::StencilOperation::Keep;
694 }
695 }
696
GetFirstIndexForDrawCall(gl::DrawElementsType indexType,const void * indices)697 uint32_t GetFirstIndexForDrawCall(gl::DrawElementsType indexType, const void *indices)
698 {
699 const size_t indexSize = gl::GetDrawElementsTypeSize(indexType);
700 const uintptr_t indexBufferByteOffset = reinterpret_cast<uintptr_t>(indices);
701 if (indexBufferByteOffset % indexSize != 0)
702 {
703 // WebGPU only allows offsetting index buffers by multiples of the index size
704 UNIMPLEMENTED();
705 }
706
707 return static_cast<uint32_t>(indexBufferByteOffset / indexSize);
708 }
709
710 } // namespace gl_wgpu
711 } // namespace rx
712