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(WGPUBufferMapAsyncStatus mapBufferStatus)86 bool IsWgpuError(WGPUBufferMapAsyncStatus mapBufferStatus)
87 {
88 return mapBufferStatus != WGPUBufferMapAsyncStatus_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
126 glExtensions->textureStorageEXT = true;
127 glExtensions->rgb8Rgba8OES = true;
128
129 // OpenGL ES caps
130 glCaps->maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
131 glCaps->max3DTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension3D);
132 glCaps->max2DTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
133 glCaps->maxArrayTextureLayers = rx::LimitToInt(limitsWgpu.maxTextureArrayLayers);
134 glCaps->maxLODBias = 0.0f;
135 glCaps->maxCubeMapTextureSize = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
136 glCaps->maxRenderbufferSize = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
137 glCaps->minAliasedPointSize = 1.0f;
138 glCaps->maxAliasedPointSize = 1.0f;
139 glCaps->minAliasedLineWidth = 1.0f;
140 glCaps->maxAliasedLineWidth = 1.0f;
141
142 // "descriptor.sampleCount must be either 1 or 4."
143 constexpr uint32_t kMaxSampleCount = 4;
144
145 glCaps->maxDrawBuffers = rx::LimitToInt(limitsWgpu.maxColorAttachments);
146 glCaps->maxFramebufferWidth = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
147 glCaps->maxFramebufferHeight = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
148 glCaps->maxFramebufferSamples = kMaxSampleCount;
149 glCaps->maxColorAttachments = rx::LimitToInt(limitsWgpu.maxColorAttachments);
150 glCaps->maxViewportWidth = rx::LimitToInt(limitsWgpu.maxTextureDimension2D);
151 glCaps->maxViewportHeight = glCaps->maxViewportWidth;
152 glCaps->maxSampleMaskWords = 1;
153 glCaps->maxColorTextureSamples = kMaxSampleCount;
154 glCaps->maxDepthTextureSamples = kMaxSampleCount;
155 glCaps->maxIntegerSamples = kMaxSampleCount;
156 glCaps->maxServerWaitTimeout = 0;
157
158 glCaps->maxVertexAttribRelativeOffset = (1u << kAttributeOffsetMaxBits) - 1;
159 glCaps->maxVertexAttribBindings =
160 rx::LimitToInt(std::min(limitsWgpu.maxVertexBuffers, limitsWgpu.maxVertexAttributes));
161 glCaps->maxVertexAttribStride =
162 rx::LimitToInt(std::min(limitsWgpu.maxVertexBufferArrayStride,
163 static_cast<uint32_t>(std::numeric_limits<uint16_t>::max())));
164 glCaps->maxElementsIndices = std::numeric_limits<GLint>::max();
165 glCaps->maxElementsVertices = std::numeric_limits<GLint>::max();
166 glCaps->vertexHighpFloat.setIEEEFloat();
167 glCaps->vertexMediumpFloat.setIEEEHalfFloat();
168 glCaps->vertexLowpFloat.setIEEEHalfFloat();
169 glCaps->fragmentHighpFloat.setIEEEFloat();
170 glCaps->fragmentMediumpFloat.setIEEEHalfFloat();
171 glCaps->fragmentLowpFloat.setIEEEHalfFloat();
172 glCaps->vertexHighpInt.setTwosComplementInt(32);
173 glCaps->vertexMediumpInt.setTwosComplementInt(16);
174 glCaps->vertexLowpInt.setTwosComplementInt(16);
175 glCaps->fragmentHighpInt.setTwosComplementInt(32);
176 glCaps->fragmentMediumpInt.setTwosComplementInt(16);
177 glCaps->fragmentLowpInt.setTwosComplementInt(16);
178
179 // Clamp the maxUniformBlockSize to 64KB (majority of devices support up to this size
180 // currently), on AMD the maxUniformBufferRange is near uint32_t max.
181 GLuint maxUniformBlockSize = static_cast<GLuint>(
182 std::min(static_cast<uint64_t>(0x10000), limitsWgpu.maxUniformBufferBindingSize));
183
184 const GLuint maxUniformVectors = maxUniformBlockSize / (sizeof(GLfloat) * 4);
185 const GLuint maxUniformComponents = maxUniformVectors * 4;
186
187 const int32_t maxPerStageUniformBuffers = rx::LimitToInt(
188 limitsWgpu.maxUniformBuffersPerShaderStage - kReservedPerStageDefaultUniformSlotCount);
189
190 // There is no additional limit to the combined number of components. We can have up to a
191 // maximum number of uniform buffers, each having the maximum number of components. Note that
192 // this limit includes both components in and out of uniform buffers.
193 //
194 // This value is limited to INT_MAX to avoid overflow when queried from glGetIntegerv().
195 const uint64_t maxCombinedUniformComponents =
196 std::min<uint64_t>(static_cast<uint64_t>(maxPerStageUniformBuffers +
197 kReservedPerStageDefaultUniformSlotCount) *
198 maxUniformComponents,
199 std::numeric_limits<GLint>::max());
200
201 for (gl::ShaderType shaderType : gl::AllShaderTypes())
202 {
203 glCaps->maxShaderUniformBlocks[shaderType] = maxPerStageUniformBuffers;
204 glCaps->maxShaderTextureImageUnits[shaderType] =
205 rx::LimitToInt(limitsWgpu.maxSamplersPerShaderStage);
206 glCaps->maxShaderStorageBlocks[shaderType] = 0;
207 glCaps->maxShaderUniformComponents[shaderType] = 0;
208 glCaps->maxShaderAtomicCounterBuffers[shaderType] = 0;
209 glCaps->maxShaderAtomicCounters[shaderType] = 0;
210 glCaps->maxShaderImageUniforms[shaderType] = 0;
211 glCaps->maxCombinedShaderUniformComponents[shaderType] = maxCombinedUniformComponents;
212 }
213
214 const GLint maxVarryingComponents = rx::LimitToInt(limitsWgpu.maxInterStageShaderComponents);
215
216 glCaps->maxVertexAttributes = rx::LimitToInt(
217 limitsWgpu.maxVertexBuffers); // WebGPU has maxVertexBuffers and maxVertexAttributes but
218 // since each vertex attribute can use a unique buffer, we
219 // are limited by the total number of vertex buffers
220 glCaps->maxVertexUniformVectors =
221 maxUniformVectors; // Uniforms are implemented using a uniform buffer, so the max number of
222 // uniforms we can support is the max buffer range divided by the size
223 // of a single uniform (4X float).
224 glCaps->maxVertexOutputComponents = maxVarryingComponents;
225
226 glCaps->maxFragmentUniformVectors = maxUniformVectors;
227 glCaps->maxFragmentInputComponents = maxVarryingComponents;
228 glCaps->minProgramTextureGatherOffset = 0;
229 glCaps->maxProgramTextureGatherOffset = 0;
230 glCaps->minProgramTexelOffset = -8;
231 glCaps->maxProgramTexelOffset = 7;
232
233 glCaps->maxComputeWorkGroupCount = {0, 0, 0};
234 glCaps->maxComputeWorkGroupSize = {0, 0, 0};
235 glCaps->maxComputeWorkGroupInvocations = 0;
236 glCaps->maxComputeSharedMemorySize = 0;
237
238 // Only 2 stages (vertex+fragment) are supported.
239 constexpr uint32_t kShaderStageCount = 2;
240
241 glCaps->maxUniformBufferBindings = maxPerStageUniformBuffers * kShaderStageCount;
242 glCaps->maxUniformBlockSize = rx::LimitToInt(limitsWgpu.maxBufferSize);
243 glCaps->uniformBufferOffsetAlignment =
244 rx::LimitToInt(limitsWgpu.minUniformBufferOffsetAlignment);
245 glCaps->maxCombinedUniformBlocks = glCaps->maxUniformBufferBindings;
246 glCaps->maxVaryingComponents = maxVarryingComponents;
247 glCaps->maxVaryingVectors = rx::LimitToInt(limitsWgpu.maxInterStageShaderVariables);
248 glCaps->maxCombinedTextureImageUnits =
249 rx::LimitToInt(limitsWgpu.maxSamplersPerShaderStage * kShaderStageCount);
250 glCaps->maxCombinedShaderOutputResources = 0;
251
252 glCaps->maxUniformLocations = maxUniformVectors;
253 glCaps->maxAtomicCounterBufferBindings = 0;
254 glCaps->maxAtomicCounterBufferSize = 0;
255 glCaps->maxCombinedAtomicCounterBuffers = 0;
256 glCaps->maxCombinedAtomicCounters = 0;
257 glCaps->maxImageUnits = 0;
258 glCaps->maxCombinedImageUniforms = 0;
259 glCaps->maxShaderStorageBufferBindings = 0;
260 glCaps->maxShaderStorageBlockSize = 0;
261 glCaps->maxCombinedShaderStorageBlocks = 0;
262 glCaps->shaderStorageBufferOffsetAlignment = 0;
263
264 glCaps->maxTransformFeedbackInterleavedComponents = 0;
265 glCaps->maxTransformFeedbackSeparateAttributes = 0;
266 glCaps->maxTransformFeedbackSeparateComponents = 0;
267
268 glCaps->lineWidthGranularity = 0.0f;
269 glCaps->minMultisampleLineWidth = 0.0f;
270 glCaps->maxMultisampleLineWidth = 0.0f;
271
272 glCaps->maxTextureBufferSize = 0;
273 glCaps->textureBufferOffsetAlignment = 0;
274
275 glCaps->maxSamples = kMaxSampleCount;
276
277 // Max version
278 *maxSupportedESVersion = gl::Version(3, 2);
279
280 // OpenGL ES texture caps
281 InitMinimumTextureCapsMap(*maxSupportedESVersion, *glExtensions, glTextureCapsMap);
282
283 // EGL caps
284 eglCaps->textureNPOT = true;
285
286 // EGL extensions
287 eglExtensions->createContextRobustness = true;
288 eglExtensions->postSubBuffer = true;
289 eglExtensions->createContext = true;
290 eglExtensions->image = true;
291 eglExtensions->imageBase = true;
292 eglExtensions->glTexture2DImage = true;
293 eglExtensions->glTextureCubemapImage = true;
294 eglExtensions->glTexture3DImage = true;
295 eglExtensions->glRenderbufferImage = true;
296 eglExtensions->getAllProcAddresses = true;
297 eglExtensions->noConfigContext = true;
298 eglExtensions->directComposition = true;
299 eglExtensions->createContextNoError = true;
300 eglExtensions->createContextWebGLCompatibility = true;
301 eglExtensions->createContextBindGeneratesResource = true;
302 eglExtensions->swapBuffersWithDamage = true;
303 eglExtensions->pixelFormatFloat = true;
304 eglExtensions->surfacelessContext = true;
305 eglExtensions->displayTextureShareGroup = true;
306 eglExtensions->displaySemaphoreShareGroup = true;
307 eglExtensions->createContextClientArrays = true;
308 eglExtensions->programCacheControlANGLE = true;
309 eglExtensions->robustResourceInitializationANGLE = true;
310 }
311
IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology)312 bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology)
313 {
314 switch (topology)
315 {
316 case wgpu::PrimitiveTopology::LineStrip:
317 case wgpu::PrimitiveTopology::TriangleStrip:
318 return true;
319
320 default:
321 return false;
322 }
323 }
324
ErrorScope(wgpu::Instance instance,wgpu::Device device,wgpu::ErrorFilter errorType)325 ErrorScope::ErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType)
326 : mInstance(instance), mDevice(device)
327 {
328 mDevice.PushErrorScope(errorType);
329 mActive = true;
330 }
331
~ErrorScope()332 ErrorScope::~ErrorScope()
333 {
334 ANGLE_UNUSED_VARIABLE(PopScope(nullptr, nullptr, nullptr, 0));
335 }
336
PopScope(ContextWgpu * context,const char * file,const char * function,unsigned int line)337 angle::Result ErrorScope::PopScope(ContextWgpu *context,
338 const char *file,
339 const char *function,
340 unsigned int line)
341 {
342 if (!mActive)
343 {
344 return angle::Result::Continue;
345 }
346 mActive = false;
347
348 bool hadError = false;
349 wgpu::Future f = mDevice.PopErrorScope(
350 wgpu::CallbackMode::WaitAnyOnly,
351 [context, file, function, line, &hadError](wgpu::PopErrorScopeStatus status,
352 wgpu::ErrorType type, char const *message) {
353 if (type == wgpu::ErrorType::NoError)
354 {
355 return;
356 }
357
358 if (context)
359 {
360 ASSERT(file);
361 ASSERT(function);
362 context->handleError(GL_INVALID_OPERATION, message, file, function, line);
363 }
364 else
365 {
366 ERR() << "Unhandled WebGPU error: " << message;
367 }
368 hadError = true;
369 });
370 mInstance.WaitAny(f, -1);
371
372 return hadError ? angle::Result::Stop : angle::Result::Continue;
373 }
374
375 } // namespace webgpu
376
377 namespace wgpu_gl
378 {
getLevelIndex(webgpu::LevelIndex levelWgpu,gl::LevelIndex baseLevel)379 gl::LevelIndex getLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel)
380 {
381 return gl::LevelIndex(levelWgpu.get() + baseLevel.get());
382 }
383
getExtents(wgpu::Extent3D wgpuExtent)384 gl::Extents getExtents(wgpu::Extent3D wgpuExtent)
385 {
386 gl::Extents glExtent;
387 glExtent.width = wgpuExtent.width;
388 glExtent.height = wgpuExtent.height;
389 glExtent.depth = wgpuExtent.depthOrArrayLayers;
390 return glExtent;
391 }
392 } // namespace wgpu_gl
393
394 namespace gl_wgpu
395 {
getLevelIndex(gl::LevelIndex levelGl,gl::LevelIndex baseLevel)396 webgpu::LevelIndex getLevelIndex(gl::LevelIndex levelGl, gl::LevelIndex baseLevel)
397 {
398 ASSERT(baseLevel <= levelGl);
399 return webgpu::LevelIndex(levelGl.get() - baseLevel.get());
400 }
401
getExtent3D(const gl::Extents & glExtent)402 wgpu::Extent3D getExtent3D(const gl::Extents &glExtent)
403 {
404 wgpu::Extent3D wgpuExtent;
405 wgpuExtent.width = glExtent.width;
406 wgpuExtent.height = glExtent.height;
407 wgpuExtent.depthOrArrayLayers = glExtent.depth;
408 return wgpuExtent;
409 }
410
GetPrimitiveTopology(gl::PrimitiveMode mode)411 wgpu::PrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode)
412 {
413 switch (mode)
414 {
415 case gl::PrimitiveMode::Points:
416 return wgpu::PrimitiveTopology::PointList;
417 case gl::PrimitiveMode::Lines:
418 return wgpu::PrimitiveTopology::LineList;
419 case gl::PrimitiveMode::LineLoop:
420 UNIMPLEMENTED();
421 return wgpu::PrimitiveTopology::LineList; // 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 UNIMPLEMENTED();
443 return wgpu::IndexFormat::Uint16; // Emulated
444 case gl::DrawElementsType::UnsignedShort:
445 return wgpu::IndexFormat::Uint16;
446 case gl::DrawElementsType::UnsignedInt:
447 return wgpu::IndexFormat::Uint32;
448
449 default:
450 UNREACHABLE();
451 return wgpu::IndexFormat::Undefined;
452 }
453 }
454
GetFrontFace(GLenum frontFace)455 wgpu::FrontFace GetFrontFace(GLenum frontFace)
456 {
457 switch (frontFace)
458 {
459 case GL_CW:
460 return wgpu::FrontFace::CW;
461 case GL_CCW:
462 return wgpu::FrontFace::CCW;
463
464 default:
465 UNREACHABLE();
466 return wgpu::FrontFace::Undefined;
467 }
468 }
469
GetCullMode(gl::CullFaceMode mode,bool cullFaceEnabled)470 wgpu::CullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled)
471 {
472 if (!cullFaceEnabled)
473 {
474 return wgpu::CullMode::None;
475 }
476
477 switch (mode)
478 {
479 case gl::CullFaceMode::Front:
480 return wgpu::CullMode::Front;
481 case gl::CullFaceMode::Back:
482 return wgpu::CullMode::Back;
483 case gl::CullFaceMode::FrontAndBack:
484 UNIMPLEMENTED();
485 return wgpu::CullMode::None; // Emulated
486 default:
487 UNREACHABLE();
488 return wgpu::CullMode::None;
489 }
490 }
491
GetColorWriteMask(bool r,bool g,bool b,bool a)492 wgpu::ColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a)
493 {
494 return (r ? wgpu::ColorWriteMask::Red : wgpu::ColorWriteMask::None) |
495 (g ? wgpu::ColorWriteMask::Green : wgpu::ColorWriteMask::None) |
496 (b ? wgpu::ColorWriteMask::Blue : wgpu::ColorWriteMask::None) |
497 (a ? wgpu::ColorWriteMask::Alpha : wgpu::ColorWriteMask::None);
498 }
499
getWgpuTextureDimension(gl::TextureType glTextureType)500 wgpu::TextureDimension getWgpuTextureDimension(gl::TextureType glTextureType)
501 {
502 wgpu::TextureDimension dimension = {};
503 switch (glTextureType)
504 {
505 case gl::TextureType::_2D:
506 case gl::TextureType::_2DMultisample:
507 case gl::TextureType::Rectangle:
508 case gl::TextureType::External:
509 case gl::TextureType::Buffer:
510 dimension = wgpu::TextureDimension::e2D;
511 break;
512 case gl::TextureType::_2DArray:
513 case gl::TextureType::_2DMultisampleArray:
514 case gl::TextureType::_3D:
515 case gl::TextureType::CubeMap:
516 case gl::TextureType::CubeMapArray:
517 case gl::TextureType::VideoImage:
518 dimension = wgpu::TextureDimension::e3D;
519 break;
520 default:
521 break;
522 }
523 return dimension;
524 }
525
getCompareFunc(const GLenum glCompareFunc)526 wgpu::CompareFunction getCompareFunc(const GLenum glCompareFunc)
527 {
528 switch (glCompareFunc)
529 {
530 case GL_NEVER:
531 return wgpu::CompareFunction::Never;
532 case GL_LESS:
533 return wgpu::CompareFunction::Less;
534 case GL_EQUAL:
535 return wgpu::CompareFunction::Equal;
536 case GL_LEQUAL:
537 return wgpu::CompareFunction::LessEqual;
538 case GL_GREATER:
539 return wgpu::CompareFunction::Greater;
540 case GL_NOTEQUAL:
541 return wgpu::CompareFunction::NotEqual;
542 case GL_GEQUAL:
543 return wgpu::CompareFunction::GreaterEqual;
544 case GL_ALWAYS:
545 return wgpu::CompareFunction::Always;
546 default:
547 UNREACHABLE();
548 return wgpu::CompareFunction::Always;
549 }
550 }
551
getStencilOp(const GLenum glStencilOp)552 wgpu::StencilOperation getStencilOp(const GLenum glStencilOp)
553 {
554 switch (glStencilOp)
555 {
556 case GL_KEEP:
557 return wgpu::StencilOperation::Keep;
558 case GL_ZERO:
559 return wgpu::StencilOperation::Zero;
560 case GL_REPLACE:
561 return wgpu::StencilOperation::Replace;
562 case GL_INCR:
563 return wgpu::StencilOperation::IncrementClamp;
564 case GL_DECR:
565 return wgpu::StencilOperation::DecrementClamp;
566 case GL_INCR_WRAP:
567 return wgpu::StencilOperation::IncrementWrap;
568 case GL_DECR_WRAP:
569 return wgpu::StencilOperation::DecrementWrap;
570 case GL_INVERT:
571 return wgpu::StencilOperation::Invert;
572 default:
573 UNREACHABLE();
574 return wgpu::StencilOperation::Keep;
575 }
576 }
577
GetFirstIndexForDrawCall(gl::DrawElementsType indexType,const void * indices)578 uint32_t GetFirstIndexForDrawCall(gl::DrawElementsType indexType, const void *indices)
579 {
580 const size_t indexSize = gl::GetDrawElementsTypeSize(indexType);
581 const uintptr_t indexBufferByteOffset = reinterpret_cast<uintptr_t>(indices);
582 if (indexBufferByteOffset % indexSize != 0)
583 {
584 // WebGPU only allows offsetting index buffers by multiples of the index size
585 UNIMPLEMENTED();
586 }
587
588 return static_cast<uint32_t>(indexBufferByteOffset / indexSize);
589 }
590
591 } // namespace gl_wgpu
592 } // namespace rx
593