ext-render-snorm.html (7627B)
1 <!-- 2 Copyright (c) 2023 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL EXT_render_snorm Conformance Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 </head> 16 <body> 17 <div id="description"></div> 18 <div id="console"></div> 19 <script> 20 "use strict"; 21 description("This test verifies the functionality of the EXT_render_snorm extension, if it is available."); 22 23 debug(""); 24 25 var wtu = WebGLTestUtils; 26 var gl = wtu.create3DContext(null, null, 2); 27 var ext; 28 29 function createTypedArray(type) { 30 switch (type) { 31 case gl.BYTE: 32 return new Int8Array(4); 33 case gl.UNSIGNED_BYTE: 34 return new Uint8Array(4); 35 case gl.SHORT: 36 return new Int16Array(4); 37 case gl.UNSIGNED_SHORT: 38 return new Uint16Array(4); 39 default: 40 return null; 41 } 42 } 43 44 function drawTest(config) { 45 wtu.drawUnitQuad(gl); 46 47 const implementationType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE); 48 const implementationFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT); 49 50 // Support for reading signed data with unsigned read type is not required 51 // but implementations may allow such conversions. Do not expect the error 52 // when the type matches the buffer type or when it's explicitly supported. 53 for (const type of [gl.BYTE, gl.UNSIGNED_BYTE, gl.SHORT, gl.UNSIGNED_SHORT]) { 54 if (type == config.type) continue; 55 if (implementationFormat != gl.RGBA || implementationType != type) { 56 gl.readPixels(0, 0, 1, 1, gl.RGBA, type, createTypedArray(type)); 57 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "reading with unsupported type fails"); 58 } 59 } 60 61 const defaultPixel = createTypedArray(config.type); 62 wtu.checkCanvasRect(gl, 0, 0, 1, 1, config.color, 63 "reading with the RGBA format and matching type", 1, 64 defaultPixel, 65 config.type, gl.RGBA); 66 67 if (implementationFormat == config.format && implementationType == config.type) { 68 const implementationPixel = createTypedArray(implementationType); 69 const color = [config.color[0]]; 70 if (config.format != gl.RED) color.push(config.color[1]); 71 if (config.format == gl.RGBA) color.push(config.color[2], config.color[3]); 72 wtu.checkCanvasRect(gl, 0, 0, 1, 1, color, 73 "reading with the exact format/type", 1, 74 implementationPixel, 75 implementationType, implementationFormat); 76 } 77 } 78 79 function renderbufferTest(config, isSupported) { 80 debug(""); 81 debug(`${config.name} renderbuffer: ` + 82 `${!isSupported || !config.color ? "NOT " : ""}supported`); 83 84 const rbo = gl.createRenderbuffer(); 85 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 86 gl.renderbufferStorage(gl.RENDERBUFFER, config.internalFormat, 1, 1); 87 if (!isSupported || !config.color) { 88 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "renderbuffer allocation failed"); 89 return; 90 } 91 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "renderbuffer allocation succeeded"); 92 93 const fbo = gl.createFramebuffer(); 94 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 95 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 96 97 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE); 98 99 drawTest(config); 100 } 101 102 function textureTest(config, isRenderable, isTexturable) { 103 debug(""); 104 debug(`${config.name} texture: ` + 105 `${!isRenderable || !config.color ? "NOT " : ""}renderable, ` + 106 `${!isTexturable ? "NOT " : ""}texturable`); 107 108 const tex = gl.createTexture(); 109 gl.bindTexture(gl.TEXTURE_2D, tex); 110 gl.texImage2D(gl.TEXTURE_2D, 0, config.internalFormat, 1, 1, 0, config.format, config.type, null); 111 if (!isTexturable) { 112 wtu.glErrorShouldBe(gl, 113 [gl.INVALID_ENUM, gl.INVALID_VALUE, gl.INVALID_OPERATION], 114 "texture allocation failed"); 115 return; 116 } 117 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture allocation succeeded"); 118 119 const fbo = gl.createFramebuffer(); 120 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 121 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 122 123 if (!isRenderable || !config.color) { 124 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT); 125 return; 126 } 127 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE); 128 129 drawTest(config); 130 } 131 132 function formatTest(isSnormEnabled, isNorm16Enabled) { 133 const program = wtu.setupProgram(gl, [wtu.simpleVertexShader, 134 wtu.simpleColorFragmentShader]); 135 gl.useProgram(program); 136 gl.uniform4f(gl.getUniformLocation(program, "u_color"), -0.0625, -0.125, -0.25, -0.5); 137 138 wtu.setupUnitQuad(gl); 139 140 const configs8 = [ 141 {name: "R8_SNORM", format: gl.RED, type: gl.BYTE, internalFormat: gl.R8_SNORM, color: [-8, 0, 0, 127]}, 142 {name: "RG8_SNORM", format: gl.RG, type: gl.BYTE, internalFormat: gl.RG8_SNORM, color: [-8, -16, 0, 127]}, 143 {name: "RGB8_SNORM", format: gl.RGB, type: gl.BYTE, internalFormat: gl.RGB8_SNORM, color: null}, 144 {name: "RGBA8_SNORM", format: gl.RGBA, type: gl.BYTE, internalFormat: gl.RGBA8_SNORM, color: [-8, -16, -32, -64]} 145 ]; 146 147 const configs16 = [ 148 {name: "R16_SNORM", format: gl.RED, type: gl.SHORT, internalFormat: 0x8F98 /* R16_SNORM_EXT */, color: [-2048, 0, 0, 32767]}, 149 {name: "RG16_SNORM", format: gl.RG, type: gl.SHORT, internalFormat: 0x8F99 /* RG16_SNORM_EXT */, color: [-2048, -4096, 0, 32767]}, 150 {name: "RGB16_SNORM", format: gl.RGB, type: gl.SHORT, internalFormat: 0x8F9A /* RGB16_SNORM_EXT */, color: null}, 151 {name: "RGBA16_SNORM", format: gl.RGBA, type: gl.SHORT, internalFormat: 0x8F9B /* RGBA16_SNORM_EXT */, color: [-2048, -4096, -8192, -16384]} 152 ]; 153 154 for (const config of configs8) { 155 renderbufferTest(config, isSnormEnabled); 156 textureTest(config, isSnormEnabled, true); 157 } 158 159 for (const config of configs16) { 160 renderbufferTest(config, isSnormEnabled && isNorm16Enabled); 161 textureTest(config, isSnormEnabled && isNorm16Enabled, isNorm16Enabled); 162 } 163 } 164 165 function runTest() { 166 if (!gl) { 167 testFailed("context does not exist"); 168 return; 169 } 170 171 testPassed("context exists"); 172 173 debug(""); 174 debug("Testing signed normalized formats with EXT_render_snorm disabled"); 175 formatTest(false, false); 176 177 ext = gl.getExtension("EXT_render_snorm"); 178 wtu.runExtensionSupportedTest(gl, "EXT_render_snorm", ext !== null); 179 180 if (ext !== null) { 181 debug(""); 182 debug("Testing signed normalized formats with only EXT_render_snorm enabled"); 183 formatTest(true, false); 184 185 if (gl.getExtension("EXT_texture_norm16")) { 186 debug(""); 187 debug("Testing signed normalized formats with EXT_render_snorm and EXT_texture_norm16 enabled"); 188 formatTest(true, true); 189 } 190 } else { 191 testPassed("No EXT_render_snorm support -- this is legal"); 192 } 193 } 194 195 runTest(); 196 197 var successfullyParsed = true; 198 </script> 199 <script src="../../js/js-test-post.js"></script> 200 </body> 201 </html>