From 733426398f204b1c7008daeb71a97fe765c83167 Mon Sep 17 00:00:00 2001 From: Jimb Esser Date: Fri, 18 Oct 2024 16:31:06 -0700 Subject: [PATCH] Test uploading individual LOD levels to 3D textures from images See: https://issues.chromium.org/issues/40910322 --- .../tex-image-and-sub-image-3d-with-image.js | 129 +++++++++++++++++- .../red-green-blue-cyan-128x128x4-mipmaps.png | Bin 0 -> 3279 bytes .../red-green-blue-cyan-8x8x4-mipmaps.png | Bin 0 -> 1833 bytes 3 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 sdk/tests/resources/red-green-blue-cyan-128x128x4-mipmaps.png create mode 100644 sdk/tests/resources/red-green-blue-cyan-8x8x4-mipmaps.png diff --git a/sdk/tests/js/tests/tex-image-and-sub-image-3d-with-image.js b/sdk/tests/js/tests/tex-image-and-sub-image-3d-with-image.js index 034bd8ab46..e69ddae3bd 100644 --- a/sdk/tests/js/tests/tex-image-and-sub-image-3d-with-image.js +++ b/sdk/tests/js/tests/tex-image-and-sub-image-3d-with-image.js @@ -15,7 +15,9 @@ function generateTest(internalFormat, pixelFormat, pixelType, prologue, resource var blueColor = [0, 0, 255]; var cyanColor = [0, 255, 255]; var imageURLs = [resourcePath + "red-green.png", - resourcePath + "red-green-blue-cyan-4x4.png"]; + resourcePath + "red-green-blue-cyan-4x4.png", + resourcePath + "red-green-blue-cyan-8x8x4-mipmaps.png", + resourcePath + "red-green-blue-cyan-128x128x4-mipmaps.png"]; function init() { @@ -55,7 +57,7 @@ function generateTest(internalFormat, pixelFormat, pixelType, prologue, resource } function uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget, - depth, sourceSubRectangle, unpackImageHeight) + depth, sourceSubRectangle, unpackImageHeight, mipmaps) { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Disable any writes to the alpha channel @@ -64,7 +66,7 @@ function generateTest(internalFormat, pixelFormat, pixelType, prologue, resource // Bind the texture to texture unit 0 gl.bindTexture(bindingTarget, texture); // Set up texture parameters - gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, mipmaps ? gl.NEAREST_MIPMAP_NEAREST : gl.NEAREST); gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); @@ -94,6 +96,26 @@ function generateTest(internalFormat, pixelFormat, pixelType, prologue, resource } else { gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, gl[pixelFormat], gl[pixelType], image); + if (mipmaps) { + // Upload mipmaps packed beneath the specified image + var sourceY = sourceSubRectangle ? sourceSubRectangle[1] : 0; + var lastWidth = uploadWidth; + var lastHeight = uploadHeight; + var lastDepth = depth; + var level = 0; + while (lastWidth > 1 || lastHeight > 1) { + sourceY += lastHeight * depth; + ++level; + lastWidth = Math.max(1, Math.floor(lastWidth/2)); + lastHeight = Math.max(1, Math.floor(lastHeight/2)); + if (bindingTarget == gl.TEXTURE_3D) { + lastDepth = Math.max(1, Math.floor(lastDepth/2)); + } + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceY); + gl.texImage3D(bindingTarget, level, gl[internalFormat], lastWidth, lastHeight, lastDepth, 0, + gl[pixelFormat], gl[pixelType], image); + } + } } gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); @@ -248,10 +270,111 @@ function generateTest(internalFormat, pixelFormat, pixelType, prologue, resource } } + function runMipMapTest(image) { + + var width = image.width; + var sourceSubRectangle = [0, 0, width, width]; + var depth = 4; + var useTexSubImage3D = false; + var useMinMax = false; + var tolerance = 3; // Since using non-0/1 values, on various formats the results won't be exact + + function runOneIteration(bindingTarget, rTextureCoord, lod, color, program) + { + debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') + + ' with bindingTarget=' + + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + ' with mipmaps from ' + + image.width + 'x' + image.height + ' with r=' + rTextureCoord + ', lod=' + lod); + + uploadImageToTexture(image, useTexSubImage3D, false, bindingTarget, depth, sourceSubRectangle, undefined, true); + + var rCoordLocation = gl.getUniformLocation(program, 'uRCoord'); + if (!rCoordLocation) { + testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform'); + return; + } + gl.uniform1f(rCoordLocation, rTextureCoord); + + if (useMinMax) { + // Note: this seems like it should work, but fails on uint textures, + // bug in test / test author, or bug in implementations? + gl.texParameterf(bindingTarget, gl.TEXTURE_MIN_LOD, lod); + gl.texParameterf(bindingTarget, gl.TEXTURE_MAX_LOD, lod); + } else { + gl.texParameteri(bindingTarget, gl.TEXTURE_BASE_LEVEL, lod); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAX_LEVEL, lod); + } + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + var coord = Math.floor(gl.canvas.height/2); + wtu.checkCanvasRect(gl, coord, coord, 2, 2, color, + "shouldBe " + color, tolerance); + + if (useMinMax) { + gl.texParameterf(bindingTarget, gl.TEXTURE_MIN_LOD, 0); + gl.texParameterf(bindingTarget, gl.TEXTURE_MAX_LOD, Infinity); + } else { + gl.texParameteri(bindingTarget, gl.TEXTURE_BASE_LEVEL, 0); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAX_LEVEL, Infinity); + } + } + + function masked(r, g, b) { + return [r, greenColor[1] ? g : 0, blueColor[2] ? b : 0]; + } + + var levels = internalFormat[0] === 'S' ? [ + // SRGB values + 0xFF, 0xB8, 0x7F + ] : [ + // Raw values from mipmaps in texture + 0xFF, 0xDD, 0xBB + ]; + var cases = [ + { rTextureCoord: 0, lod: 0, color: masked(levels[0], 0, 0) }, + { rTextureCoord: 0.33, lod: 0, color: masked(0, levels[0], 0) }, + { rTextureCoord: 0.66, lod: 0, color: masked(0, 0, levels[0]) }, + { rTextureCoord: 1, lod: 0, color: masked(0, levels[0], levels[0]) }, + { rTextureCoord: 0, lod: 1, color: masked(levels[1], 0, 0) }, + { rTextureCoord: 1, lod: 1, color: masked(0, levels[1], 0) }, + { rTextureCoord: 0, lod: 2, color: masked(levels[2], 0, 0) }, + ]; + + var program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + for (var i in cases) { + runOneIteration(gl.TEXTURE_3D, cases[i].rTextureCoord, cases[i].lod, + cases[i].color, program); + } + cases = [ + { rTextureCoord: 0, lod: 0, color: masked(levels[0], 0, 0) }, + { rTextureCoord: 1, lod: 0, color: masked(0, levels[0], 0) }, + { rTextureCoord: 2, lod: 0, color: masked(0, 0, levels[0]) }, + { rTextureCoord: 3, lod: 0, color: masked(0, levels[0], levels[0]) }, + { rTextureCoord: 0, lod: 1, color: masked(levels[1], 0, 0) }, + { rTextureCoord: 1, lod: 1, color: masked(0, levels[1], 0) }, + { rTextureCoord: 2, lod: 1, color: masked(0, 0, levels[1]) }, + { rTextureCoord: 3, lod: 1, color: masked(0, levels[1], levels[1]) }, + { rTextureCoord: 0, lod: 2, color: masked(levels[2], 0, 0) }, + { rTextureCoord: 1, lod: 2, color: masked(0, levels[2], 0) }, + { rTextureCoord: 2, lod: 2, color: masked(0, 0, levels[2]) }, + { rTextureCoord: 3, lod: 2, color: masked(0, levels[2], levels[2]) }, + ]; + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + for (var i in cases) { + runOneIteration(gl.TEXTURE_2D_ARRAY, cases[i].rTextureCoord, cases[i].lod, + cases[i].color, program); + } + } + function runTest(imageMap) { runRedGreenTest(imageMap[imageURLs[0]]); runRedGreenBlueCyanTest(imageMap[imageURLs[1]]); + runMipMapTest(imageMap[imageURLs[2]]); + runMipMapTest(imageMap[imageURLs[3]]); wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); finishTest(); } diff --git a/sdk/tests/resources/red-green-blue-cyan-128x128x4-mipmaps.png b/sdk/tests/resources/red-green-blue-cyan-128x128x4-mipmaps.png new file mode 100644 index 0000000000000000000000000000000000000000..c2e34c11333d46bb277fbb7b7d316114c165265f GIT binary patch literal 3279 zcmb_dZ)_7~7=PQrHdux@lLbwX<7NyPuJ@;RZSSP8v7%c-=Q3(GqlUh{_w9PFy*uu1 zYX`cKfmYqyzg86eb2UTd~72CptZLrHb9<502&sX{lxMmwx1)94Q9^^HUKS;xPKow zd1?y)jc;m+A!jIlKv9ic03suW1BIMP&;ab-TQH$If*mS_hc!J)|9NhbrZg0#2cp5cKgGc%j>X8vuM)cl2)b4^p9OSSAsX{KR+e#rym;5Tkc9&V2DnXo)DBa}- zq=w@CRJUPaN)GUh%5gjuCYBfyBC@=T5;!5qav@fb7=cqbUXdiK{G&-Y3#FBT*fZr| z>nd#lnJSdwiDwfW(Tlsj9Mz*KSt8*aH}zuZVN-l zuo8xmt#qotk}@So0gl=+sOiYa+dJ>rfMd|XQJQp3WO$C@BMDwqcutXch6^hkw*-wF zNK22egoYG8qzJ*gphPnWI`DyDq$+8{%0W`FmV?8XHT7Yd@@Q1LjjUmjz$Ck1DT{bq z>D6rq>MHJyMQKuVK+}*C3Z;;Qk;;US6l5e$_lDh{7B~d}aT0mPSSkW>@XU9XMAKN{?ofW{sC8 z;vha;wz3*kQh@?hSKU!sb=!&&U0&9zFi=|sOK$TSOq|}Q-AgdrNIQ9G;jUrA)&u3l z-Ya<`?RD^IGQh5d=S!AT3h!`33DMrLN5($UX5Fxoz`pVQLMG7jxNJW0DNxe*~ znt}Q-CTAr}ufCYtlz6W`ESshJ6~nqGD)SyW=z^jVvvZBic2+%YnRj*9+DO zPZqg67P>S009b#mH`bLX{BrF|*W3QC&Brc2b*XWtxK5;etv#I$ZN&Wa^qI5P)hT$% z`T1Y{gVx#XESHp!pO|LikJm`-{H_cO? z$Kor}J3cR=9fKe4eXS6A$OWId?z{S=i#vTiIu&;*>AZaMMK{OdXIndt_nr42=xk5= uKPgUt#-#7euTT5^>%{rT=N8{sX#D8=?UT>XMxtcKK=1y(*vI>l6aNEmTF&4A literal 0 HcmV?d00001 diff --git a/sdk/tests/resources/red-green-blue-cyan-8x8x4-mipmaps.png b/sdk/tests/resources/red-green-blue-cyan-8x8x4-mipmaps.png new file mode 100644 index 0000000000000000000000000000000000000000..7d939cac4dee0708f2e626ae34fd521727794cab GIT binary patch literal 1833 zcmb_d&2QX96nAo{`l(V-0daDjwgQQle@LrWKV*Fc`< z8PGIL6G#Lo#%W1LAT5^W9$LJhd7PE8NY%740mWQFTXBa8TE5VH7NaP8Tg5!jA zxsjz^O|8?2S43arGO%Q4O;`j0Zl^^_Qp(#cUz3{kIA$0{1U9Xv4X7Jhz(jTgJdY88 zP@@?_&LDEUxqVB}-Kw&4dsf*y%ygT?1tBv-K&g#D=$H|J(BjQ7M3h>5ZvR;x%cVv7 zC-zel z%Jn;s7Vd2*m#^(Vyf!@0-gtO*@b#s)?{3}KzZ@K#y7K1L$oyyV$3LI^t}iGTo$to) TJo#g(I?URu>#d(Y{_6g}H0wBl literal 0 HcmV?d00001