• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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