Skip to content

Commit 6c8c68c

Browse files
committed
calcGPUSize
1 parent 0dcbabc commit 6c8c68c

9 files changed

Lines changed: 93 additions & 74 deletions

File tree

examples/src/examples/graphics/texture-array.example.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@ assetListLoader.load(() => {
105105
const textureArrayOptions = {
106106
name: 'textureArrayImages',
107107
format: pc.PIXELFORMAT_SRGBA8,
108+
dimension: pc.TEXTUREDIMENSION_2D_ARRAY,
108109
width: 1024,
109110
height: 1024,
110-
arrayLength: 4, // array texture with 4 textures
111+
slices: 4, // array texture with 4 textures
111112
magFilter: pc.FILTER_NEAREST,
112113
minFilter: pc.FILTER_NEAREST_MIPMAP_NEAREST,
113114
mipmaps: true,
@@ -130,7 +131,7 @@ assetListLoader.load(() => {
130131
const mipmaps = generateMipmaps(textureArrayOptions.width, textureArrayOptions.height);
131132
const levels = mipmaps.map((data) => {
132133
const textures = [];
133-
for (let i = 0; i < textureArrayOptions.arrayLength; i++) {
134+
for (let i = 0; i < textureArrayOptions.slices; i++) {
134135
textures.push(data);
135136
}
136137
return textures;

src/framework/handlers/texture.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ const _completePartialMipmapChain = function (texture) {
6161

6262
if (!(texture._format === PIXELFORMAT_RGBA8 ||
6363
texture._format === PIXELFORMAT_RGBA32F) ||
64-
texture._volume ||
64+
texture.volume ||
6565
texture._compressed ||
6666
texture._levels.length === 1 ||
6767
texture._levels.length === requiredMipLevels ||
68-
isHtmlElement(texture._cubemap ? texture._levels[0][0] : texture._levels[0])) {
68+
isHtmlElement(texture.cubemap ? texture._levels[0][0] : texture._levels[0])) {
6969
return;
7070
}
7171

@@ -99,7 +99,7 @@ const _completePartialMipmapChain = function (texture) {
9999
for (let level = texture._levels.length; level < requiredMipLevels; ++level) {
100100
const width = Math.max(1, texture._width >> (level - 1));
101101
const height = Math.max(1, texture._height >> (level - 1));
102-
if (texture._cubemap) {
102+
if (texture.cubemap) {
103103
const mips = [];
104104
for (let face = 0; face < 6; ++face) {
105105
mips.push(downsample(width, height, texture._levels[level - 1][face]));
@@ -110,7 +110,7 @@ const _completePartialMipmapChain = function (texture) {
110110
}
111111
}
112112

113-
texture._levelsUpdated = texture._cubemap ? [[true, true, true, true, true, true]] : [true];
113+
texture._levelsUpdated = texture.cubemap ? [[true, true, true, true, true, true]] : [true];
114114
};
115115

116116
/**

src/framework/xr/xr-view.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ class XrView extends EventHandler {
172172

173173
this._textureDepth = new Texture(device, {
174174
format: this._manager.views.depthPixelFormat,
175-
arrayLength: (viewsCount === 1) ? 0 : viewsCount,
175+
array: viewsCount > 1,
176+
slices: viewsCount,
176177
mipmaps: false,
177178
addressU: ADDRESS_CLAMP_TO_EDGE,
178179
addressV: ADDRESS_CLAMP_TO_EDGE,

src/platform/graphics/texture-utils.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Debug } from '../../core/debug.js';
22
import {
33
pixelFormatInfo,
4-
PIXELFORMAT_PVRTC_2BPP_RGB_1, PIXELFORMAT_PVRTC_2BPP_RGBA_1
4+
PIXELFORMAT_PVRTC_2BPP_RGB_1, PIXELFORMAT_PVRTC_2BPP_RGBA_1,
5+
TEXTUREDIMENSION_3D
56
} from './constants.js';
67

78
/**
@@ -26,7 +27,7 @@ class TextureUtils {
2627
*
2728
* @param {number} width - Texture's width.
2829
* @param {number} height - Texture's height.
29-
* @param {number} [depth] - Texture's depth. Defaults to 1.
30+
* @param {number} [depth] - Texture's depth slices. Defaults to 1.
3031
* @returns {number} The number of mip levels required for the texture.
3132
*/
3233
static calcMipLevelsCount(width, height, depth = 1) {
@@ -38,7 +39,7 @@ class TextureUtils {
3839
*
3940
* @param {number} width - Texture's width.
4041
* @param {number} height - Texture's height.
41-
* @param {number} depth - Texture's depth.
42+
* @param {number} depth - Texture's depth slices.
4243
* @param {number} format - Texture's pixel format PIXELFORMAT_***.
4344
* @returns {number} The number of bytes of GPU memory required for the texture.
4445
*/
@@ -68,16 +69,17 @@ class TextureUtils {
6869
/**
6970
* Calculate the GPU memory required for a texture.
7071
*
72+
* @param {string} dimension - Texture's dimension
7173
* @param {number} width - Texture's width.
7274
* @param {number} height - Texture's height.
73-
* @param {number} depth - Texture's depth.
75+
* @param {number} slices - Texture's slices.
7476
* @param {number} format - Texture's pixel format PIXELFORMAT_***.
7577
* @param {boolean} mipmaps - True if the texture includes mipmaps, false otherwise.
76-
* @param {boolean} cubemap - True is the texture is a cubemap, false otherwise.
7778
* @returns {number} The number of bytes of GPU memory required for the texture.
7879
*/
79-
static calcGpuSize(width, height, depth, format, mipmaps, cubemap) {
80+
static calcGpuSize(width, height, slices, format, isVolume, mipmaps) {
8081
let result = 0;
82+
let depth = isVolume ? slices : 1;
8183

8284
while (1) {
8385
result += TextureUtils.calcLevelGpuSize(width, height, depth, format);
@@ -91,7 +93,7 @@ class TextureUtils {
9193
depth = Math.max(depth >> 1, 1);
9294
}
9395

94-
return result * (cubemap ? 6 : 1);
96+
return result * (isVolume ? 1 : slices);
9597
}
9698
}
9799

src/platform/graphics/texture.js

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import {
1313
TEXTUREPROJECTION_NONE, TEXTUREPROJECTION_CUBE,
1414
TEXTURETYPE_DEFAULT, TEXTURETYPE_RGBM, TEXTURETYPE_RGBE, TEXTURETYPE_RGBP,
1515
isIntegerPixelFormat, FILTER_NEAREST, TEXTURELOCK_NONE, TEXTURELOCK_READ,
16-
requiresManualGamma
16+
requiresManualGamma,
17+
TEXTUREDIMENSION_2D,
18+
TEXTUREDIMENSION_3D,
19+
TEXTUREDIMENSION_2D_ARRAY,
20+
TEXTUREDIMENSION_CUBE
1721
} from './constants.js';
1822
import { TextureUtils } from './texture-utils.js';
1923

@@ -103,7 +107,15 @@ class Texture {
103107
* @param {string} [options.name] - The name of the texture. Defaults to null.
104108
* @param {number} [options.width] - The width of the texture in pixels. Defaults to 4.
105109
* @param {number} [options.height] - The height of the texture in pixels. Defaults to 4.
106-
* @param {number} [options.depth] - The number of depth slices in a 3D texture.
110+
* @param {number} [options.slices] - The number of depth slices in a 3D texture, the number of textures
111+
* in a texture array or the number of faces for a cubemap.
112+
* @param {string} [options.dimension] - The texture dimension type. Can be:
113+
* - {@link TEXTUREDIMENSION_2D}
114+
* - {@link TEXTUREDIMENSION_2D_ARRAY}
115+
* - {@link TEXTUREDIMENSION_3D}
116+
* - {@link TEXTUREDIMENSION_CUBE}
117+
* Defaults to {@link TEXTUREDIMENSION_2D}. Alternatively, you can specify the dimension using
118+
* the options.cubemap, options.volume or options.array properties.
107119
* @param {number} [options.format] - The pixel format of the texture. Can be:
108120
*
109121
* - {@link PIXELFORMAT_R8}
@@ -157,9 +169,8 @@ class Texture {
157169
* texture. Default is true.
158170
* @param {boolean} [options.cubemap] - Specifies whether the texture is to be a cubemap.
159171
* Defaults to false.
160-
* @param {number} [options.arrayLength] - Specifies whether the texture is to be a 2D texture array.
161-
* When passed in as undefined or < 1, this is not an array texture. If >= 1, this is an array texture.
162-
* Defaults to undefined.
172+
* @param {boolean} [options.array] - Specifies whether the texture is to be a 2D texture array.
173+
* Defaults to false.
163174
* @param {boolean} [options.volume] - Specifies whether the texture is to be a 3D volume.
164175
* Defaults to false.
165176
* @param {string} [options.type] - Specifies the texture type. Can be:
@@ -194,7 +205,7 @@ class Texture {
194205
* Defaults to {@link FUNC_LESS}.
195206
* @param {Uint8Array[]|HTMLCanvasElement[]|HTMLImageElement[]|HTMLVideoElement[]|Uint8Array[][]} [options.levels]
196207
* - Array of Uint8Array or other supported browser interface; or a two-dimensional array
197-
* of Uint8Array if options.arrayLength is defined and greater than zero.
208+
* of Uint8Array if options.dimension is {@link TEXTUREDIMENSION_2D_ARRAY}.
198209
* @param {boolean} [options.storage] - Defines if texture can be used as a storage texture by
199210
* a compute shader. Defaults to false.
200211
* @param {boolean} [options.immediate] - If set and true, the texture will be uploaded to the GPU immediately.
@@ -223,13 +234,22 @@ class Texture {
223234
Debug.assert(this.device, "Texture constructor requires a graphicsDevice to be valid");
224235
Debug.assert(!options.width || Number.isInteger(options.width), "Texture width must be an integer number, got", options);
225236
Debug.assert(!options.height || Number.isInteger(options.height), "Texture height must be an integer number, got", options);
226-
Debug.assert(!options.depth || Number.isInteger(options.depth), "Texture depth must be an integer number, got", options);
237+
Debug.assert(!options.slices || Number.isInteger(options.slices), "Texture slices must be an integer number, got", options);
227238

228239
this.name = options.name ?? '';
229240

241+
this._dimension = options.dimension ?? TEXTUREDIMENSION_2D;
242+
this._dimension = options.array ? TEXTUREDIMENSION_2D_ARRAY : this._dimension;
243+
this._dimension = options.cubemap ? TEXTUREDIMENSION_CUBE : this._dimension;
244+
this._dimension = options.volume ? TEXTUREDIMENSION_3D : this._dimension;
245+
230246
this._width = Math.floor(options.width ?? 4);
231247
this._height = Math.floor(options.height ?? 4);
232248

249+
this._slices = Math.floor(options.slices ?? (this._dimension === TEXTUREDIMENSION_CUBE ? 6 : 1));
250+
251+
Debug.assert((this._dimension === TEXTUREDIMENSION_CUBE ? this._slices === 6 : true), "Texture cube map must have 6 slices");
252+
233253
this._format = options.format ?? PIXELFORMAT_RGBA8;
234254
this._compressed = isCompressedPixelFormat(this._format);
235255
this._integerFormat = isIntegerPixelFormat(this._format);
@@ -239,12 +259,7 @@ class Texture {
239259
options.magFilter = FILTER_NEAREST;
240260
}
241261

242-
this._volume = options.volume ?? false;
243-
this._depth = Math.floor(options.depth ?? 1);
244-
this._arrayLength = Math.floor(options.arrayLength ?? 0);
245-
246262
this._storage = options.storage ?? false;
247-
this._cubemap = options.cubemap ?? false;
248263
this._flipY = options.flipY ?? false;
249264
this._premultiplyAlpha = options.premultiplyAlpha ?? false;
250265

@@ -264,7 +279,7 @@ class Texture {
264279
Debug.assert(!options.hasOwnProperty('swizzleGGGR'), 'Use options.type.');
265280

266281
this.projection = TEXTUREPROJECTION_NONE;
267-
if (this._cubemap) {
282+
if (this.cubemap) {
268283
this.projection = TEXTUREPROJECTION_CUBE;
269284
} else if (options.projection && options.projection !== TEXTUREPROJECTION_CUBE) {
270285
this.projection = options.projection;
@@ -282,7 +297,7 @@ class Texture {
282297
if (this._levels) {
283298
this.upload(options.immediate ?? false);
284299
} else {
285-
this._levels = this._cubemap ? [[null, null, null, null, null, null]] : [null];
300+
this._levels = this.cubemap ? [[null, null, null, null, null, null]] : [null];
286301
}
287302

288303
// track the texture
@@ -330,10 +345,10 @@ class Texture {
330345
*
331346
* @param {number} width - The new width of the texture.
332347
* @param {number} height - The new height of the texture.
333-
* @param {number} [depth] - The new depth of the texture. Defaults to 1.
348+
* @param {number} [slices] - The new number of slices for the texture. Defaults to 1.
334349
* @ignore
335350
*/
336-
resize(width, height, depth = 1) {
351+
resize(width, height, slices = 1) {
337352

338353
// destroy texture impl
339354
const device = this.device;
@@ -342,7 +357,7 @@ class Texture {
342357

343358
this._width = Math.floor(width);
344359
this._height = Math.floor(height);
345-
this._depth = Math.floor(depth);
360+
this._slices = Math.floor(slices);
346361

347362
// re-create the implementation
348363
this.impl = device.createTextureImpl(this);
@@ -530,7 +545,7 @@ class Texture {
530545
* @type {number}
531546
*/
532547
set addressW(addressW) {
533-
if (!this._volume) {
548+
if (!this.volume) {
534549
Debug.warn("pc.Texture#addressW: Can't set W addressing mode for a non-3D texture.");
535550
return;
536551
}
@@ -684,7 +699,16 @@ class Texture {
684699
* @type {number}
685700
*/
686701
get depth() {
687-
return this._depth;
702+
return this._dimension === TEXTUREDIMENSION_3D ? this._slices : 1;
703+
}
704+
705+
/**
706+
* The number of textures in a texture array or the number of faces for a cubemap.
707+
*
708+
* @type {number}
709+
*/
710+
get slices() {
711+
return this._slices;
688712
}
689713

690714
/**
@@ -726,12 +750,12 @@ class Texture {
726750
* @type {boolean}
727751
*/
728752
get cubemap() {
729-
return this._cubemap;
753+
return this._dimension === TEXTUREDIMENSION_CUBE;
730754
}
731755

732756
get gpuSize() {
733757
const mips = this.pot && this._mipmaps && !(this._compressed && this._levels.length === 1);
734-
return TextureUtils.calcGpuSize(this._width, this._height, this._depth, this._format, mips, this._cubemap);
758+
return TextureUtils.calcGpuSize(this._width, this._height, this._slices, this._format, this.volume, mips);
735759
}
736760

737761
/**
@@ -740,16 +764,7 @@ class Texture {
740764
* @type {boolean}
741765
*/
742766
get array() {
743-
return this._arrayLength > 0;
744-
}
745-
746-
/**
747-
* Returns the number of textures inside this texture if this is a 2D array texture or 0 otherwise.
748-
*
749-
* @type {number}
750-
*/
751-
get arrayLength() {
752-
return this._arrayLength;
767+
return this._dimension === TEXTUREDIMENSION_2D_ARRAY;
753768
}
754769

755770
/**
@@ -758,7 +773,7 @@ class Texture {
758773
* @type {boolean}
759774
*/
760775
get volume() {
761-
return this._volume;
776+
return this._dimension === TEXTUREDIMENSION_3D;
762777
}
763778

764779
/**
@@ -821,7 +836,7 @@ class Texture {
821836

822837
// Force a full resubmission of the texture to the GPU (used on a context restore event)
823838
dirtyAll() {
824-
this._levelsUpdated = this._cubemap ? [[true, true, true, true, true, true]] : [true];
839+
this._levelsUpdated = this.cubemap ? [[true, true, true, true, true, true]] : [true];
825840

826841
this._needsUpload = true;
827842
this._needsMipmapsUpload = this._mipmaps;
@@ -871,7 +886,7 @@ class Texture {
871886
// allocate storage for this mip level
872887
const width = Math.max(1, this._width >> options.level);
873888
const height = Math.max(1, this._height >> options.level);
874-
const depth = Math.max(1, this._depth >> options.level);
889+
const depth = Math.max(1, (this._dimension === TEXTUREDIMENSION_3D ? this._slices : 1) >> options.level);
875890
const data = new ArrayBuffer(TextureUtils.calcLevelGpuSize(width, height, depth, this._format));
876891
levels[options.level] = new (getPixelFormatArrayType(this._format))(data);
877892
}
@@ -894,7 +909,7 @@ class Texture {
894909
let invalid = false;
895910
let width, height;
896911

897-
if (this._cubemap) {
912+
if (this.cubemap) {
898913
if (source[0]) {
899914
// rely on first face sizes
900915
width = source[0].width || 0;
@@ -946,7 +961,7 @@ class Texture {
946961
this._height = 4;
947962

948963
// remove levels
949-
if (this._cubemap) {
964+
if (this.cubemap) {
950965
for (let i = 0; i < 6; i++) {
951966
this._levels[mipLevel][i] = null;
952967
this._levelsUpdated[mipLevel][i] = true;

src/platform/graphics/webgl/webgl-render-target.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class WebglRenderTarget {
155155
gl.framebufferTexture2D(
156156
gl.FRAMEBUFFER,
157157
attachmentBaseConstant + i,
158-
colorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
158+
colorBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
159159
colorBuffer.impl._glTexture,
160160
0
161161
);
@@ -178,11 +178,11 @@ class WebglRenderTarget {
178178
// Attach
179179
if (target._stencil) {
180180
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT,
181-
depthBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
181+
depthBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
182182
target._depthBuffer.impl._glTexture, 0);
183183
} else {
184184
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
185-
depthBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
185+
depthBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
186186
target._depthBuffer.impl._glTexture, 0);
187187
}
188188
} else if (target._depth) {
@@ -306,7 +306,7 @@ class WebglRenderTarget {
306306
const dstFramebuffer = gl.createFramebuffer();
307307
device.setFramebuffer(dstFramebuffer);
308308
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
309-
colorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
309+
colorBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
310310
colorBuffer.impl._glTexture,
311311
0
312312
);

0 commit comments

Comments
 (0)