From 4e28a224d0f2f7990ee107bfa52044e09106a68b Mon Sep 17 00:00:00 2001 From: Ib Green Date: Wed, 3 Jul 2024 12:03:13 -0400 Subject: [PATCH] chore: Restore texture tests (#2123) --- docs/api-reference/core/device-features.mdx | 1 - .../core/resources/framebuffer.md | 4 +- docs/api-reference/core/texture-formats.mdx | 1 - docs/upgrade-guide.md | 35 +++--- modules/core/src/adapter/device.ts | 1 - .../gpu-type-utils/decode-texture-format.ts | 101 +++++++++++++----- .../src/gpu-type-utils/texture-formats.ts | 15 +-- .../adapter/resources/command-buffer.spec.ts | 2 - .../test/adapter/resources/texture.spec.ts | 99 +++++++++-------- .../decode-texture-format.spec.ts | 14 +-- .../src/adapter/converters/texture-formats.ts | 26 ++--- .../device-helpers/webgl-device-features.ts | 1 - .../polyfills/polyfill-webgl1-extensions.ts | 32 +++--- 13 files changed, 178 insertions(+), 154 deletions(-) diff --git a/docs/api-reference/core/device-features.mdx b/docs/api-reference/core/device-features.mdx index 529bc4eaf..b59970538 100644 --- a/docs/api-reference/core/device-features.mdx +++ b/docs/api-reference/core/device-features.mdx @@ -43,7 +43,6 @@ Each device has a `device.features` field that holds a `DeviceFeatures` object w | `shader-conservative-depth-webgl` | | GLSL enable early depth test optimizations | `EXT_conservative_depth` | | `shader-clip-cull-distance-webgl` | | GLSL `gl_ClipDistance[]/gl_CullDistance[]` | `WEBGL_clip_cull_distance` | | **Texture Extensions** | -| `depth24unorm-stencil8` | | | `GL.UNSIGNED_INT_24_8_WEBGL` | | `depth32float-stencil8` | | | N/A | | `rg11b10ufloat-renderable` | | rg11b10ufloat textures renderable | N/A | | `float32-renderable-webgl` | | float32 textures renderable | `EXT_color_buffer_float` | diff --git a/docs/api-reference/core/resources/framebuffer.md b/docs/api-reference/core/resources/framebuffer.md index 023c80cc8..819d866b0 100644 --- a/docs/api-reference/core/resources/framebuffer.md +++ b/docs/api-reference/core/resources/framebuffer.md @@ -22,7 +22,7 @@ const framebuffer = device.createFramebuffer({ width: window.innerWidth, height: window.innerHeight, colorAttachments: [{format: 'rgb8unorm'}], - depthStencilAttachment: {format: 'depth24unorm-stencil8'} + depthStencilAttachment: {format: 'depth24plus-stencil8'} }); ``` @@ -36,7 +36,7 @@ const size = { const framebuffer = device.createFramebuffer({ ...size, colorAttachments: [device.createTexture({format: 'rgb8unorm', ...size})], - depthStencilAttachment: device.createTexture({format: 'depth24unorm-stencil8', ...size}) + depthStencilAttachment: device.createTexture({format: 'depth24plus-stencil8', ...size}) }); ``` diff --git a/docs/api-reference/core/texture-formats.mdx b/docs/api-reference/core/texture-formats.mdx index 4697cd7d9..f00013177 100644 --- a/docs/api-reference/core/texture-formats.mdx +++ b/docs/api-reference/core/texture-formats.mdx @@ -81,7 +81,6 @@ Note that even though a GPU supports creating and sampling textures of a certain | `depth24plus` | | | | Platform dependent: Maps to "`depth24unorm`" or `depth32float`. | | `depth24plus-stencil81` | | | | Platform dependent: Maps to "`depth24unorm`" or `depth32float`. | | `depth32float` | | | | Higher precision than `depth24unorm` in representable range (0.0 to 1.0) | -| `depth24unorm-stencil8` | | | | Platform dependent: Check via `depth24unorm-stencil8` feature. | | `depth32float-stencil8` | | | | Platform dependent: Check via `depth32float-stencil8` feature. | | **`texture-compression-bc(5)`** | | | | _[S3 Texture Compression][s3tc_wiki], aka BC (Block Compression) using FourCC DXTn file identifiers. 4-6x compression._ | | `bc1-rgb-unorm-webgl` | | | | BC1 / DXT1: 16 input pixels in 64 bits. | diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index cae5bb8ff..a3e80cc72 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -16,24 +16,29 @@ Some deprectations and minor breaking changes are necessary as WebGPU support is **@luma.gl/core** -| Updated API | Status | Replacement | -| ------------------------------ | ---------- | -------------------------------------------------------------------------------------------- | -| `luma.registerDevices()` | Deprecated | Use [`luma.registerAdapters()`](/docs/api-reference/core/luma#lumaregisteradapters) instead. | -| `Texture.props.data` (Promise) | Changed | Textures no longer accept promises, use `AsyncTexture` class instead. | -| `triangle-fan-webgl` | Removed | Rebuild your geometries using `triangle-strip`. | -| `line-loop-webgl` | Removed | Rebuild your geometries`line-list`. | -| `glsl` template string | Removed | Enable syntax highlighting in vscode using `/* glsl */` comment instead | -| `Parameters.blend` | New | Explicit control over color blending | +| Updated API | Status | Replacement | Comment | +| ------------------------------ | ---------- | -------------------------------------- | --------------------------------------------------------------- | +| `Parameters.blend` | New | | Explicit activation of color blending | +| `luma.registerDevices()` | Deprecated | [`luma.registerAdapters()`][adapters]. | Adapters provide a cleaner way to work with GPU backends. | +| `Texture.props.data` (Promise) | Changed | `AsyncTexture` class | Textures no longer accept promises. | +| `triangle-fan-webgl` | Removed | `triangle-strip`. | Reorganize your geometries | +| `line-loop-webgl` | Removed | `line-list`. | Reorganize your geometries | +| `glsl` shader template string | Removed | `/* glsl */` comment | Enable syntax highlighting in vscode using before shader string | +| `depth24unorm-stencil8` | Removed | `depth24plus-stencil8` | The `TextureFormat` was removed from the WebGPU spec | +| `rgb8unorm-unsized` | Removed | `rgb8unorm` | No longer support unsized WebGL1 `TextureFormat` | +| `rgba8unorm-unsized` | Removed | `rgb8aunorm` | No longer support unsized WebGL1 `TextureFormat` | + +[adapters]: /docs/api-reference/core/luma#lumaregisteradapters **@luma.gl/shadertools** -| Updated API | Status | Replacement | -| ------------------------------------ | ------- | ----------------------------------------------------------------------- | -| `ShaderModuleInstance` | Removed | Type has been removed. Use `ShaderModule` instead. | -| `initializeShaderModule()` | Changed | Stores initialized information on the original shader module object. | -| `ShaderModuleInstance.getUniforms()` | Removed | Use `getShaderModuleUniforms(module, ...)` instead. | -| `getDependencyGraph()` | Removed | Use `getShaderModuleDependencies(module)` instead. | -| `glsl` template string | Removed | Enable syntax highlighting in vscode using `/* glsl */` comment instead | +| Updated API | Status | Replacement | Comment | +| ------------------------------------ | ------- | --------------------------------------- | -------------------------------------------------- | +| `ShaderModuleInstance` | Removed | Use `ShaderModule` instead. | Type has been removed. | +| `initializeShaderModule()` | Changed | | Initializes the original shader module object | +| `ShaderModuleInstance.getUniforms()` | Removed | `getShaderModuleUniforms(module, ...)`. | Interact directly with the shader module | +| `getDependencyGraph()` | Removed | `getShaderModuleDependencies(module)` . | Interact directly with the shader module | +| `glsl` template string | Removed | `/* glsl */` comment | Enable syntax highlighting in vscode using comment | ## Upgrading to v9.0 diff --git a/modules/core/src/adapter/device.ts b/modules/core/src/adapter/device.ts index 576f8edea..b1620cecf 100644 --- a/modules/core/src/adapter/device.ts +++ b/modules/core/src/adapter/device.ts @@ -145,7 +145,6 @@ export type WebGPUDeviceFeature = | 'indirect-first-instance' | 'timestamp-query' | 'shader-f16' - | 'depth24unorm-stencil8' | 'depth32float-stencil8' | 'rg11b10ufloat-renderable' // Is the rg11b10ufloat texture format renderable? | 'float32-filterable' // Is the float32 format filterable? diff --git a/modules/core/src/gpu-type-utils/decode-texture-format.ts b/modules/core/src/gpu-type-utils/decode-texture-format.ts index c05039ebb..3888e7f06 100644 --- a/modules/core/src/gpu-type-utils/decode-texture-format.ts +++ b/modules/core/src/gpu-type-utils/decode-texture-format.ts @@ -11,19 +11,37 @@ const COMPRESSED_TEXTURE_FORMAT_PREFIXES = [ 'bc1', 'bc2', 'bc3', 'bc4', 'bc5', 'bc6', 'bc7', 'etc1', 'etc2', 'eac', 'atc', 'astc', 'pvrtc' ]; -const REGEX = /^(rg?b?a?)([0-9]*)([a-z]*)(-srgb)?(-webgl|-unsized)?$/; +const REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/; export type DecodedTextureFormat = { - format: 'r' | 'rg' | 'rgb' | 'rgba'; + /** String describing which channels this texture has */ + channels: 'r' | 'rg' | 'rgb' | 'rgba' | 'bgra'; + /** Number of components (corresponds to channels string) */ components: 1 | 2 | 3 | 4; + /** What is the data type of each component */ dataType?: VertexType; - srgb: boolean; - webgl: boolean; - unsized: boolean; + /** Number of bytes per pixel */ + bpp?: number; + /** Depth stencil formats */ + a?: 'depth' | 'stencil' | 'depth-stencil'; + /** SRGB texture format? */ + srgb?: boolean; + /** WebGL specific texture format? */ + webgl?: boolean; + /** byteLength */ byteLength: number; + /** Is this an integer or floating point format? */ integer: boolean; + /** Is this a signed or unsigned format? */ signed: boolean; + /** Is this a normalized integer format? */ normalized: boolean; + /** Is this a compressed texture format */ + compressed?: boolean; + /** Block size for ASTC formats (texture must be a multiple) */ + blockWidth?: number; + /** Block size for ASTC formats (texture must be a multiple) */ + blockHeight?: number; }; /** @@ -39,19 +57,23 @@ export function isTextureFormatCompressed(textureFormat: TextureFormat): boolean export function decodeTextureFormat(format: TextureFormat): DecodedTextureFormat { const matches = REGEX.exec(format as string); if (matches) { - const [, format, length, type, srgb, suffix] = matches; + const [, channels, length, type, srgb, suffix] = matches; if (format) { const dataType = `${type}${length}` as VertexType; const decodedType = decodeVertexType(dataType); - return { - format: format as 'r' | 'rg' | 'rgb' | 'rgba', - components: format.length as 1 | 2 | 3 | 4, - // dataType - overwritten by decodedType - srgb: srgb === '-srgb', - unsized: suffix === '-unsized', - webgl: suffix === '-webgl', + const info: DecodedTextureFormat = { + channels: channels as 'r' | 'rg' | 'rgb' | 'rgba', + components: channels.length as 1 | 2 | 3 | 4, ...decodedType }; + if (suffix === '-webgl') { + info.webgl = true; + } + // dataType - overwritten by decodedType + if (srgb === '-srgb') { + info.srgb = true; + } + return info; } } @@ -60,42 +82,67 @@ export function decodeTextureFormat(format: TextureFormat): DecodedTextureFormat // https://www.w3.org/TR/webgpu/#texture-format-caps -const EXCEPTIONS: Partial> = { +const EXCEPTIONS: Partial>> = { // Packed 16 bit formats - 'rgba4unorm-webgl': {format: 'rgba', bpp: 2}, - 'rgb565unorm-webgl': {format: 'rgb', bpp: 2}, - 'rgb5a1unorm-webgl': {format: 'rgba', bbp: 2}, + 'rgba4unorm-webgl': {channels: 'rgba', bpp: 2}, + 'rgb565unorm-webgl': {channels: 'rgb', bpp: 2}, + 'rgb5a1unorm-webgl': {channels: 'rgba', bpp: 2}, // Packed 32 bit formats - rgb9e5ufloat: {format: 'rgb', bbp: 4}, - rg11b10ufloat: {format: 'rgb', bbp: 4}, - rgb10a2unorm: {format: 'rgba', bbp: 4}, - 'rgb10a2uint-webgl': {format: 'rgba', bbp: 4}, + rgb9e5ufloat: {channels: 'rgb', bpp: 4}, + rg11b10ufloat: {channels: 'rgb', bpp: 4}, + rgb10a2unorm: {channels: 'rgba', bpp: 4}, + 'rgb10a2uint-webgl': {channels: 'rgba', bpp: 4}, // Depth/stencil stencil8: {components: 1, bpp: 1, a: 'stencil'}, depth16unorm: {components: 1, bpp: 2, a: 'depth'}, depth24plus: {components: 1, bpp: 3, a: 'depth'}, depth32float: {components: 1, bpp: 4, a: 'depth'}, 'depth24plus-stencil8': {components: 2, bpp: 4, a: 'depth-stencil'}, - // "depth24unorm-stencil8" feature - 'depth24unorm-stencil8': {components: 2, bpp: 4, a: 'depth-stencil'}, // "depth32float-stencil8" feature 'depth32float-stencil8': {components: 2, bpp: 4, a: 'depth-stencil'} }; function decodeNonStandardFormat(format: TextureFormat): DecodedTextureFormat { + if (isTextureFormatCompressed(format)) { + const info: DecodedTextureFormat = { + channels: 'rgb', + components: 3, + byteLength: 1, + srgb: false, + compressed: true + } as DecodedTextureFormat; + const blockSize = getCompressedTextureBlockSize(format); + if (blockSize) { + info.blockWidth = blockSize.blockWidth; + info.blockHeight = blockSize.blockHeight; + } + return info; + } const data = EXCEPTIONS[format]; if (!data) { throw new Error(`Unknown format ${format}`); } return { - format: data.format || '', - components: data.components || data.format?.length || 1, + channels: data.channels || '', + components: data.components || data.channels?.length || 1, byteLength: data.bpp || 1, - srgb: false, - unsized: false + srgb: false } as DecodedTextureFormat; } +/** Parses ASTC block widths from format string */ +function getCompressedTextureBlockSize( + format: string +): {blockWidth: number; blockHeight: number} | null { + const REGEX = /.*-(\d+)x(\d+)-.*/; + const matches = REGEX.exec(format); + if (matches) { + const [, blockWidth, blockHeight] = matches; + return {blockWidth: Number(blockWidth), blockHeight: Number(blockHeight)}; + } + return null; +} + /* 'r8unorm': {s: "float"}, // ✓ ✓ ✓ }, 'r8snorm': {s: "float"}, // ✓ }, diff --git a/modules/core/src/gpu-type-utils/texture-formats.ts b/modules/core/src/gpu-type-utils/texture-formats.ts index 8dfcc939d..2ac14c284 100644 --- a/modules/core/src/gpu-type-utils/texture-formats.ts +++ b/modules/core/src/gpu-type-utils/texture-formats.ts @@ -12,16 +12,11 @@ export type DepthStencilTextureFormat = | 'depth24plus' | 'depth24plus-stencil8' | 'depth32float' - // device.features.has('depth24unorm-stencil8') - | 'depth24unorm-stencil8' // device.features.has('depth32float-stencil8') | 'depth32float-stencil8'; /** Texture formats for color attachments */ -export type ColorTextureFormat = - | WebGPUColorTextureFormat - | WebGL2ColorTextureFormat - | UnsizedColorTextureFormat; +export type ColorTextureFormat = WebGPUColorTextureFormat | WebGL2ColorTextureFormat; export type WebGPUColorTextureFormat = // 8-bit formats @@ -103,6 +98,7 @@ export type WebGPUColorTextureFormat = // ASTC compressed formats usable if "texture-compression-astc" is both // supported by the device/user agent and enabled in requestDevice. + // Textures must be multiple of block size (encoded in format string). | 'astc-4x4-unorm' | 'astc-4x4-unorm-srgb' | 'astc-5x4-unorm' @@ -132,13 +128,6 @@ export type WebGPUColorTextureFormat = | 'astc-12x12-unorm' | 'astc-12x12-unorm-srgb'; -/** Unsized texture formats (the only formats supported by WebGL1) */ -export type UnsizedColorTextureFormat = 'rgb8unorm-unsized' | 'rgba8unorm-unsized'; -// 'r8unorm-unsized' | -// 'ra8unorm-unsized' | -// 'rgb8unorm-srgb-unsized' | -// 'rgba8unorm-srgb-unsized' - /** Sized formats in WebGL 2 that are not (yet?) supported by WebGPU */ export type WebGL2ColorTextureFormat = | 'r16unorm-webgl' diff --git a/modules/core/test/adapter/resources/command-buffer.spec.ts b/modules/core/test/adapter/resources/command-buffer.spec.ts index cd3a5a755..aa3afe2ff 100644 --- a/modules/core/test/adapter/resources/command-buffer.spec.ts +++ b/modules/core/test/adapter/resources/command-buffer.spec.ts @@ -200,8 +200,6 @@ type WebGLTextureInfo = { }; const WEBGL_TEXTURE_FORMATS: Record = { - // Unsized texture format - more performance - 'rgb8unorm-unsized': {dataFormat: GL.RGB, types: [GL.UNSIGNED_BYTE, GL.UNSIGNED_SHORT_5_6_5]}, // TODO: format: GL.RGBA type: GL.FLOAT is supported in WebGL1 when 'OES_texure_float' is suported // we need to update this table structure to specify extensions (gl1ext: 'OES_texure_float', gl2ext: false) for each type. rgba8unorm: { diff --git a/modules/core/test/adapter/resources/texture.spec.ts b/modules/core/test/adapter/resources/texture.spec.ts index da137c1e1..ab0a74e71 100644 --- a/modules/core/test/adapter/resources/texture.spec.ts +++ b/modules/core/test/adapter/resources/texture.spec.ts @@ -5,11 +5,14 @@ import test from 'tape-promise/tape'; import {webglDevice, getTestDevices} from '@luma.gl/test-utils'; -import {Device, Texture, TextureFormat} from '@luma.gl/core'; +import {Device, Texture, TextureFormat, decodeTextureFormat} from '@luma.gl/core'; import {GL} from '@luma.gl/constants'; // TODO(v9): Avoid import from `@luma.gl/webgl` in core tests. -import {TEXTURE_FORMATS} from '@luma.gl/webgl/adapter/converters/texture-formats'; +import { + TEXTURE_FORMATS, + getTextureFormatWebGL +} from '../../../../webgl/src/adapter/converters/texture-formats'; import {SAMPLER_PARAMETERS} from './sampler.spec'; import {WEBGLTexture} from '@luma.gl/webgl/adapter/resources/webgl-texture'; @@ -63,13 +66,6 @@ test('Texture#depth/stencil formats', async t => { t.end(); }); -test.skip('Texture#format deduction', async t => { - for (const device of await getTestDevices()) { - testFormatDeduction(t, device); - } - t.end(); -}); - const DEFAULT_TEXTURE_DATA = new Uint8Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]); @@ -93,6 +89,49 @@ const TEXTURE_DATA = { // [GL.UNSIGNED_SHORT_5_6_5]: v => [v >> 11 / 32, v >> 6 % 64 / 64, v % 32 * 32] // }; +test('Texture#format simple creation', async t => { + for (const device of await getTestDevices()) { + for (const [formatName, formatInfo] of Object.entries(TEXTURE_FORMATS)) { + if (['stencil8'].includes(formatName)) { + continue; + } + + if (device.isTextureFormatSupported(formatName)) { + // For compressed textures there may be a block size that we need to be a multiple of + const decodedFormat = decodeTextureFormat(formatName); + const width = decodedFormat.blockWidth ?? 4; + const height = decodedFormat.blockHeight ?? 4; + + let texture: Texture; + t.doesNotThrow(() => { + texture = device.createTexture({ + format: formatName, + height, + width + }); + }, `Texture(${device.type},${formatName}) creation OK`); + + t.equals(texture.format, formatName, `Texture(${device.type},${formatName}).format OK`); + if (device.type === 'webgl') { + // const formatInfo = getTextureFormatWebGL(forma) + const expectedInternalFormat = formatInfo.gl; + t.equals( + texture.glInternalFormat, + expectedInternalFormat, + `Texture(${device.type},${formatName}).glInternal OK` + ); + // const expectedType = formatInfo.types?.[0]; + // const expectedDataFormat = formatInfo.dataFormat; + // t.equals(texture.glType, expectedType, `Texture(${formatName}).type OK`); + // t.equals(texture.glFormat, expectedDataFormat, `Texture(${formatName}).glFormat OK`); + } + texture.destroy(); + } + } + } + t.end(); +}); + function testFormatCreation(t, device: Device, withData: boolean = false) { for (const [textureFormat, formatInfo] of Object.entries(TEXTURE_FORMATS)) { const format = textureFormat as TextureFormat; @@ -134,33 +173,6 @@ function testFormatCreation(t, device: Device, withData: boolean = false) { } } -function testFormatDeduction(t, device: Device) { - for (const [formatName, formatInfo] of Object.entries(TEXTURE_FORMATS)) { - const expectedType = formatInfo.types[0]; - const expectedDataFormat = formatInfo.dataFormat; - const options = { - format: Number(format), - height: 1, - width: 1 - }; - if (device.isTextureFormatSupported({format})) { - const texture = device.createTexture(options); - const msg = `Texture({format: ${device.getGLKey(format)}}) created`; - t.equals(texture.format, Number(format), msg); - t.equals(texture.type, expectedType, msg); - t.equals(texture.dataFormat, expectedDataFormat, msg); - texture.destroy(); - } - } -} - -test.skip('Texture#format deduction', async t => { - for (const device of await getTestDevices()) { - testFormatDeduction(t, device); - } - t.end(); -}); - test.skip('Texture#format creation', async t => { for (const device of await getTestDevices()) { testFormatCreation(t, device); @@ -175,21 +187,6 @@ test.skip('Texture#format creation with data', async t => { t.end(); }); -/* -test.skip('Texture#WebGL2 format creation', t => { - - for (const format in TEXTURE_FORMATS) { - } - let texture = webglDevice.createTexture({}); - t.ok(texture instanceof Texture, 'Texture construction successful'); - - texture = texture.destroy(); - t.ok(texture instanceof Texture, 'Texture delete successful'); - - t.end(); -}); -*/ - test.skip('Texture#setParameters', t => { const texture = webglDevice.createTexture({}); t.ok(texture instanceof Texture, 'Texture construction successful'); diff --git a/modules/core/test/gpu-type-utils/decode-texture-format.spec.ts b/modules/core/test/gpu-type-utils/decode-texture-format.spec.ts index 29e352a44..139c58f2e 100644 --- a/modules/core/test/gpu-type-utils/decode-texture-format.spec.ts +++ b/modules/core/test/gpu-type-utils/decode-texture-format.spec.ts @@ -8,15 +8,15 @@ import {decodeTextureFormat, TextureFormat} from '@luma.gl/core'; // prettier-ignore const TEST_CASES: {format: TextureFormat, result: any}[] = [ // 8-bit formats - {format: 'r8unorm', result: { format: 'r', components: 1, dataType: 'uint8', byteLength: 1, integer: false, signed: false, normalized: true, srgb: false, webgl: false, unsized: false }}, - {format: 'r8snorm', result: { format: 'r', components: 1, dataType: 'sint8', byteLength: 1, integer: false, signed: true, normalized: true, srgb: false, webgl: false, unsized: false }}, - {format: 'r8uint', result: { format: 'r', components: 1, dataType: 'uint8', byteLength: 1, integer: true, signed: false, normalized: false, srgb: false, webgl: false, unsized: false }}, - {format: 'r8sint', result: { format: 'r', components: 1, dataType: 'sint8', byteLength: 1, integer: true, signed: true, normalized: false, srgb: false, webgl: false, unsized: false }}, + {format: 'r8unorm', result: {channels: 'r', components: 1, dataType: 'uint8', byteLength: 1, integer: false, signed: false, normalized: true}}, + {format: 'r8snorm', result: {channels: 'r', components: 1, dataType: 'sint8', byteLength: 1, integer: false, signed: true, normalized: true}}, + {format: 'r8uint', result: {channels: 'r', components: 1, dataType: 'uint8', byteLength: 1, integer: true, signed: false, normalized: false}}, + {format: 'r8sint', result: {channels: 'r', components: 1, dataType: 'sint8', byteLength: 1, integer: true, signed: true, normalized: false}}, // 16-bit formats - {format: 'r16uint', result: { format: 'r', components: 1, dataType: 'uint16', byteLength: 2, integer: true, signed: false, normalized: false, srgb: false, webgl: false, unsized: false }}, - {format: 'r16sint', result: { format: 'r', components: 1, dataType: 'sint16', byteLength: 2, integer: true, signed: true, normalized: false, srgb: false, webgl: false, unsized: false }}, - {format: 'r16float', result: { format: 'r', components: 1, dataType: 'float16', byteLength: 2, integer: false, signed: false, normalized: false, srgb: false, webgl: false, unsized: false }} + {format: 'r16uint', result: {channels: 'r', components: 1, dataType: 'uint16', byteLength: 2, integer: true, signed: false, normalized: false}}, + {format: 'r16sint', result: {channels: 'r', components: 1, dataType: 'sint16', byteLength: 2, integer: true, signed: true, normalized: false}}, + {format: 'r16float', result: {channels: 'r', components: 1, dataType: 'float16', byteLength: 2, integer: false, signed: false, normalized: false }} ]; test('api#decodeTextureFormat', t => { diff --git a/modules/webgl/src/adapter/converters/texture-formats.ts b/modules/webgl/src/adapter/converters/texture-formats.ts index 7195b45d8..89a1a1cfe 100644 --- a/modules/webgl/src/adapter/converters/texture-formats.ts +++ b/modules/webgl/src/adapter/converters/texture-formats.ts @@ -141,15 +141,6 @@ type Format = { */ // prettier-ignore export const TEXTURE_FORMATS: Record = { - // Unsized formats that leave the precision up to the driver. TODO - Fix bpp constants - 'rgb8unorm-unsized': {gl: GL.RGB, b: 4, c: 2, bpp: 4, - dataFormat: GL.RGB, types: [GL.UNSIGNED_BYTE, GL.UNSIGNED_SHORT_5_6_5]}, - 'rgba8unorm-unsized': {gl: GL.RGBA, b: 4, c: 2, bpp: 4, - dataFormat: GL.RGBA, types: [GL.UNSIGNED_BYTE, GL.UNSIGNED_SHORT_4_4_4_4, GL.UNSIGNED_SHORT_5_5_5_1]}, - // 'r8unorm-unsized': {gl: GL.LUMINANCE, b: 4, c: 2, bpp: 4}, - // 'rgb8unorm-srgb-unsized': {gl: GL.SRGB_EXT, b: 4, c: 2, bpp: 4, gl1Ext: SRGB}, - // 'rgba8unorm-srgb-unsized': {gl: GL.SRGB_ALPHA_EXT, b: 4, c: 2, bpp: 4, gl1Ext: SRGB}, - // 8-bit formats 'r8unorm': {gl: GL.R8, b: 1, c: 1, rb: true}, 'r8snorm': {gl: GL.R8_SNORM, b: 1, c: 1, render: snorm8_renderable}, @@ -239,9 +230,6 @@ export const TEXTURE_FORMATS: Record = { // The depth component of the "depth24plus" and "depth24plus-stencil8" formats may be implemented as either a 24-bit depth value or a "depth32float" value. 'depth24plus-stencil8': {gl: GL.DEPTH24_STENCIL8, b: 4, c: 2, p: 1, attachment: GL.DEPTH_STENCIL_ATTACHMENT, rb: true, depthTexture: true, dataFormat: GL.DEPTH_STENCIL, types: [GL.UNSIGNED_INT_24_8]}, - // "depth24unorm-stencil8" feature - 'depth24unorm-stencil8': {gl: GL.DEPTH24_STENCIL8, b: 4, c: 2, p: 1, attachment: GL.DEPTH_STENCIL_ATTACHMENT, - dataFormat: GL.DEPTH_STENCIL, types: [GL.UNSIGNED_INT_24_8], rb: true}, // "depth32float-stencil8" feature - TODO below is render buffer only? 'depth32float-stencil8': {gl: GL.DEPTH32F_STENCIL8, b: 5, c: 2, p: 1, attachment: GL.DEPTH_STENCIL_ATTACHMENT, dataFormat: GL.DEPTH_STENCIL, types: [GL.FLOAT_32_UNSIGNED_INT_24_8_REV], rb: true}, @@ -469,6 +457,10 @@ export function isTextureFormatSupported( if (info.gl === undefined) { return false; } + const feature = info.f; + if (feature) { + return checkTextureFeature(gl, feature, extensions); + } // Check extensions const extension = info.x || info.gl2ext; if (extension) { @@ -586,13 +578,12 @@ export function getTextureFormatWebGL(format: TextureFormat): { internalFormat: webglFormat, format: formatData?.dataFormat || - getWebGLPixelDataFormat(decoded.format, decoded.integer, decoded.normalized, webglFormat), + getWebGLPixelDataFormat(decoded.channels, decoded.integer, decoded.normalized, webglFormat), // depth formats don't have a type type: decoded.dataType ? getGLFromVertexType(decoded.dataType) : formatData?.types?.[0] || GL.UNSIGNED_BYTE, - // @ts-expect-error - compressed: decoded.compressed + compressed: decoded.compressed || false }; } @@ -619,7 +610,7 @@ export function getTextureFormatBytesPerPixel(format: TextureFormat): number { // DATA TYPE HELPERS export function getWebGLPixelDataFormat( - dataFormat: string, + channels: 'r' | 'rg' | 'rgb' | 'rgba' | 'bgra', integer: boolean, normalized: boolean, format: GL @@ -629,11 +620,12 @@ export function getWebGLPixelDataFormat( return format; } // prettier-ignore - switch (dataFormat) { + switch (channels) { case 'r': return integer && !normalized ? GL.RED_INTEGER : GL.RED; case 'rg': return integer && !normalized ? GL.RG_INTEGER : GL.RG; case 'rgb': return integer && !normalized ? GL.RGB_INTEGER : GL.RGB; case 'rgba': return integer && !normalized ? GL.RGBA_INTEGER : GL.RGBA; + case 'bgra': throw new Error('bgra pixels not supported by WebGL'); default: return GL.RGBA; } } diff --git a/modules/webgl/src/adapter/device-helpers/webgl-device-features.ts b/modules/webgl/src/adapter/device-helpers/webgl-device-features.ts index a34bb15ef..206147e8e 100644 --- a/modules/webgl/src/adapter/device-helpers/webgl-device-features.ts +++ b/modules/webgl/src/adapter/device-helpers/webgl-device-features.ts @@ -21,7 +21,6 @@ const WEBGL_FEATURES: Partial> = { // 'timestamp-query' // GPUQueryType "timestamp-query" // "indirect-first-instance" // Textures are handled by getTextureFeatures() - // 'depth24unorm-stencil8' // GPUTextureFormat 'depth24unorm-stencil8' // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8' // optional WebGL features diff --git a/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts b/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts index 123042ead..b9219ba90 100644 --- a/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts +++ b/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts @@ -149,22 +149,22 @@ export function polyfillWebGL1Extensions(gl: WebGL2RenderingContext): void { // Update unsized WebGL1 formats to sized WebGL2 formats // todo move to texture format file -export function getInternalFormat(gl: WebGL2RenderingContext, format: GL, type: GL): GL { - // webgl2 texture formats - // https://webgl2fundamentals.org/webgl/lessons/webgl-data-textures.html - switch (format) { - case GL.DEPTH_COMPONENT: - return GL.DEPTH_COMPONENT24; - case GL.DEPTH_STENCIL: - return GL.DEPTH24_STENCIL8; - case GL.RGBA: - return type === GL.HALF_FLOAT ? GL.RGBA16F : GL.RGBA32F; - case GL.RGB: - return type === GL.HALF_FLOAT ? GL.RGB16F : GL.RGB32F; - default: - return format; - } -} +// export function getInternalFormat(gl: WebGL2RenderingContext, format: GL, type: GL): GL { +// // webgl2 texture formats +// // https://webgl2fundamentals.org/webgl/lessons/webgl-data-textures.html +// switch (format) { +// case GL.DEPTH_COMPONENT: +// return GL.DEPTH_COMPONENT24; +// case GL.DEPTH_STENCIL: +// return GL.DEPTH24_STENCIL8; +// case GL.RGBA: +// return type === GL.HALF_FLOAT ? GL.RGBA16F : GL.RGBA32F; +// case GL.RGB: +// return type === GL.HALF_FLOAT ? GL.RGB16F : GL.RGB32F; +// default: +// return format; +// } +// } /* // texture type to update on the fly