Skip to content

Commit 24d4328

Browse files
committed
calcGPUSize
1 parent 15fd1bc commit 24d4328

File tree

9 files changed

+93
-74
lines changed

9 files changed

+93
-74
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,11 @@ assetListLoader.load(() => {
131131

132132
const textureArrayOptions = {
133133
name: 'textureArrayImages',
134+
dimension: pc.TEXTUREDIMENSION_2D_ARRAY,
134135
format: pc.PIXELFORMAT_R8_G8_B8_A8,
135136
width: 1024,
136137
height: 1024,
137-
arrayLength: 4, // array texture with 4 textures
138+
slices: 4, // array texture with 4 textures
138139
magFilter: pc.FILTER_NEAREST,
139140
minFilter: pc.FILTER_NEAREST_MIPMAP_NEAREST,
140141
mipmaps: true,
@@ -157,7 +158,7 @@ assetListLoader.load(() => {
157158
const mipmaps = generateMipmaps(textureArrayOptions.width, textureArrayOptions.height);
158159
const levels = mipmaps.map((data) => {
159160
const textures = [];
160-
for (let i = 0; i < textureArrayOptions.arrayLength; i++) {
161+
for (let i = 0; i < textureArrayOptions.slices; i++) {
161162
textures.push(data);
162163
}
163164
return textures;

src/framework/handlers/texture.js

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

6161
if (!(texture._format === PIXELFORMAT_RGBA8 ||
6262
texture._format === PIXELFORMAT_RGBA32F) ||
63-
texture._volume ||
63+
texture.volume ||
6464
texture._compressed ||
6565
texture._levels.length === 1 ||
6666
texture._levels.length === requiredMipLevels ||
67-
isHtmlElement(texture._cubemap ? texture._levels[0][0] : texture._levels[0])) {
67+
isHtmlElement(texture.cubemap ? texture._levels[0][0] : texture._levels[0])) {
6868
return;
6969
}
7070

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

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

115115
/**

src/framework/xr/xr-view.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ class XrView extends EventHandler {
168168
if (this._manager.views.supportedDepth && this._manager.views.availableDepth) {
169169
this._textureDepth = new Texture(device, {
170170
format: this._manager.views.depthPixelFormat,
171-
arrayLength: (viewsCount === 1) ? 0 : viewsCount,
171+
array: viewsCount > 1,
172+
slices: viewsCount,
172173
mipmaps: false,
173174
addressU: ADDRESS_CLAMP_TO_EDGE,
174175
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
* @ignore
@@ -69,17 +70,18 @@ class TextureUtils {
6970
/**
7071
* Calculate the GPU memory required for a texture.
7172
*
73+
* @param {string} dimension - Texture's dimension
7274
* @param {number} width - Texture's width.
7375
* @param {number} height - Texture's height.
74-
* @param {number} depth - Texture's depth.
76+
* @param {number} slices - Texture's slices.
7577
* @param {number} format - Texture's pixel format PIXELFORMAT_***.
7678
* @param {boolean} mipmaps - True if the texture includes mipmaps, false otherwise.
77-
* @param {boolean} cubemap - True is the texture is a cubemap, false otherwise.
7879
* @returns {number} The number of bytes of GPU memory required for the texture.
7980
* @ignore
8081
*/
81-
static calcGpuSize(width, height, depth, format, mipmaps, cubemap) {
82+
static calcGpuSize(width, height, slices, format, isVolume, mipmaps) {
8283
let result = 0;
84+
let depth = isVolume ? slices : 1;
8385

8486
while (1) {
8587
result += TextureUtils.calcLevelGpuSize(width, height, depth, format);
@@ -93,7 +95,7 @@ class TextureUtils {
9395
depth = Math.max(depth >> 1, 1);
9496
}
9597

96-
return result * (cubemap ? 6 : 1);
98+
return result * (isVolume ? 1 : slices);
9799
}
98100
}
99101

src/platform/graphics/texture.js

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ import {
1515
TEXTURELOCK_WRITE,
1616
TEXTUREPROJECTION_NONE, TEXTUREPROJECTION_CUBE,
1717
TEXTURETYPE_DEFAULT, TEXTURETYPE_RGBM, TEXTURETYPE_RGBE, TEXTURETYPE_RGBP,
18-
isIntegerPixelFormat, FILTER_NEAREST, TEXTURELOCK_NONE, TEXTURELOCK_READ
18+
isIntegerPixelFormat, FILTER_NEAREST, TEXTURELOCK_NONE, TEXTURELOCK_READ,
19+
TEXTUREDIMENSION_2D,
20+
TEXTUREDIMENSION_3D,
21+
TEXTUREDIMENSION_2D_ARRAY,
22+
TEXTUREDIMENSION_CUBE
1923
} from './constants.js';
2024

2125
let id = 0;
@@ -101,7 +105,15 @@ class Texture {
101105
* @param {string} [options.name] - The name of the texture. Defaults to null.
102106
* @param {number} [options.width] - The width of the texture in pixels. Defaults to 4.
103107
* @param {number} [options.height] - The height of the texture in pixels. Defaults to 4.
104-
* @param {number} [options.depth] - The number of depth slices in a 3D texture.
108+
* @param {number} [options.slices] - The number of depth slices in a 3D texture, the number of textures
109+
* in a texture array or the number of faces for a cubemap.
110+
* @param {string} [options.dimension] - The texture dimension type. Can be:
111+
* - {@link TEXTUREDIMENSION_2D}
112+
* - {@link TEXTUREDIMENSION_2D_ARRAY}
113+
* - {@link TEXTUREDIMENSION_3D}
114+
* - {@link TEXTUREDIMENSION_CUBE}
115+
* Defaults to {@link TEXTUREDIMENSION_2D}. Alternatively, you can specify the dimension using
116+
* the options.cubemap, options.volume or options.array properties.
105117
* @param {number} [options.format] - The pixel format of the texture. Can be:
106118
*
107119
* - {@link PIXELFORMAT_R8}
@@ -155,9 +167,8 @@ class Texture {
155167
* texture. Default is true.
156168
* @param {boolean} [options.cubemap] - Specifies whether the texture is to be a cubemap.
157169
* Defaults to false.
158-
* @param {number} [options.arrayLength] - Specifies whether the texture is to be a 2D texture array.
159-
* When passed in as undefined or < 1, this is not an array texture. If >= 1, this is an array texture.
160-
* Defaults to undefined.
170+
* @param {boolean} [options.array] - Specifies whether the texture is to be a 2D texture array.
171+
* Defaults to false.
161172
* @param {boolean} [options.volume] - Specifies whether the texture is to be a 3D volume.
162173
* Defaults to false.
163174
* @param {string} [options.type] - Specifies the texture type. Can be:
@@ -192,7 +203,7 @@ class Texture {
192203
* Defaults to {@link FUNC_LESS}.
193204
* @param {Uint8Array[]|HTMLCanvasElement[]|HTMLImageElement[]|HTMLVideoElement[]|Uint8Array[][]} [options.levels]
194205
* - Array of Uint8Array or other supported browser interface; or a two-dimensional array
195-
* of Uint8Array if options.arrayLength is defined and greater than zero.
206+
* of Uint8Array if options.dimension is {@link TEXTUREDIMENSION_2D_ARRAY}.
196207
* @param {boolean} [options.storage] - Defines if texture can be used as a storage texture by
197208
* a compute shader. Defaults to false.
198209
* @param {boolean} [options.immediate] - If set and true, the texture will be uploaded to the GPU immediately.
@@ -221,13 +232,22 @@ class Texture {
221232
Debug.assert(this.device, "Texture constructor requires a graphicsDevice to be valid");
222233
Debug.assert(!options.width || Number.isInteger(options.width), "Texture width must be an integer number, got", options);
223234
Debug.assert(!options.height || Number.isInteger(options.height), "Texture height must be an integer number, got", options);
224-
Debug.assert(!options.depth || Number.isInteger(options.depth), "Texture depth must be an integer number, got", options);
235+
Debug.assert(!options.slices || Number.isInteger(options.slices), "Texture slices must be an integer number, got", options);
225236

226237
this.name = options.name ?? '';
227238

239+
this._dimension = options.dimension ?? TEXTUREDIMENSION_2D;
240+
this._dimension = options.array ? TEXTUREDIMENSION_2D_ARRAY : this._dimension;
241+
this._dimension = options.cubemap ? TEXTUREDIMENSION_CUBE : this._dimension;
242+
this._dimension = options.volume ? TEXTUREDIMENSION_3D : this._dimension;
243+
228244
this._width = Math.floor(options.width ?? 4);
229245
this._height = Math.floor(options.height ?? 4);
230246

247+
this._slices = Math.floor(options.slices ?? (this._dimension === TEXTUREDIMENSION_CUBE ? 6 : 1));
248+
249+
Debug.assert((this._dimension === TEXTUREDIMENSION_CUBE ? this._slices === 6 : true), "Texture cube map must have 6 slices");
250+
231251
this._format = options.format ?? PIXELFORMAT_RGBA8;
232252
this._compressed = isCompressedPixelFormat(this._format);
233253
this._integerFormat = isIntegerPixelFormat(this._format);
@@ -237,12 +257,7 @@ class Texture {
237257
options.magFilter = FILTER_NEAREST;
238258
}
239259

240-
this._volume = options.volume ?? false;
241-
this._depth = Math.floor(options.depth ?? 1);
242-
this._arrayLength = Math.floor(options.arrayLength ?? 0);
243-
244260
this._storage = options.storage ?? false;
245-
this._cubemap = options.cubemap ?? false;
246261
this._flipY = options.flipY ?? false;
247262
this._premultiplyAlpha = options.premultiplyAlpha ?? false;
248263

@@ -262,7 +277,7 @@ class Texture {
262277
Debug.assert(!options.hasOwnProperty('swizzleGGGR'), 'Use options.type.');
263278

264279
this.projection = TEXTUREPROJECTION_NONE;
265-
if (this._cubemap) {
280+
if (this.cubemap) {
266281
this.projection = TEXTUREPROJECTION_CUBE;
267282
} else if (options.projection && options.projection !== TEXTUREPROJECTION_CUBE) {
268283
this.projection = options.projection;
@@ -280,7 +295,7 @@ class Texture {
280295
if (this._levels) {
281296
this.upload(options.immediate ?? false);
282297
} else {
283-
this._levels = this._cubemap ? [[null, null, null, null, null, null]] : [null];
298+
this._levels = this.cubemap ? [[null, null, null, null, null, null]] : [null];
284299
}
285300

286301
// track the texture
@@ -328,10 +343,10 @@ class Texture {
328343
*
329344
* @param {number} width - The new width of the texture.
330345
* @param {number} height - The new height of the texture.
331-
* @param {number} [depth] - The new depth of the texture. Defaults to 1.
346+
* @param {number} [slices] - The new number of slices for the texture. Defaults to 1.
332347
* @ignore
333348
*/
334-
resize(width, height, depth = 1) {
349+
resize(width, height, slices = 1) {
335350

336351
// destroy texture impl
337352
const device = this.device;
@@ -340,7 +355,7 @@ class Texture {
340355

341356
this._width = Math.floor(width);
342357
this._height = Math.floor(height);
343-
this._depth = Math.floor(depth);
358+
this._slices = Math.floor(slices);
344359

345360
// re-create the implementation
346361
this.impl = device.createTextureImpl(this);
@@ -508,7 +523,7 @@ class Texture {
508523
* @type {number}
509524
*/
510525
set addressW(addressW) {
511-
if (!this._volume) {
526+
if (!this.volume) {
512527
Debug.warn("pc.Texture#addressW: Can't set W addressing mode for a non-3D texture.");
513528
return;
514529
}
@@ -637,7 +652,16 @@ class Texture {
637652
* @type {number}
638653
*/
639654
get depth() {
640-
return this._depth;
655+
return this._dimension === TEXTUREDIMENSION_3D ? this._slices : 1;
656+
}
657+
658+
/**
659+
* The number of textures in a texture array or the number of faces for a cubemap.
660+
*
661+
* @type {number}
662+
*/
663+
get slices() {
664+
return this._slices;
641665
}
642666

643667
/**
@@ -679,12 +703,12 @@ class Texture {
679703
* @type {boolean}
680704
*/
681705
get cubemap() {
682-
return this._cubemap;
706+
return this._dimension === TEXTUREDIMENSION_CUBE;
683707
}
684708

685709
get gpuSize() {
686710
const mips = this.pot && this._mipmaps && !(this._compressed && this._levels.length === 1);
687-
return TextureUtils.calcGpuSize(this._width, this._height, this._depth, this._format, mips, this._cubemap);
711+
return TextureUtils.calcGpuSize(this._width, this._height, this._slices, this._format, this.volume, mips);
688712
}
689713

690714
/**
@@ -693,16 +717,7 @@ class Texture {
693717
* @type {boolean}
694718
*/
695719
get array() {
696-
return this._arrayLength > 0;
697-
}
698-
699-
/**
700-
* Returns the number of textures inside this texture if this is a 2D array texture or 0 otherwise.
701-
*
702-
* @type {number}
703-
*/
704-
get arrayLength() {
705-
return this._arrayLength;
720+
return this._dimension === TEXTUREDIMENSION_2D_ARRAY;
706721
}
707722

708723
/**
@@ -711,7 +726,7 @@ class Texture {
711726
* @type {boolean}
712727
*/
713728
get volume() {
714-
return this._volume;
729+
return this._dimension === TEXTUREDIMENSION_3D;
715730
}
716731

717732
/**
@@ -772,7 +787,7 @@ class Texture {
772787

773788
// Force a full resubmission of the texture to the GPU (used on a context restore event)
774789
dirtyAll() {
775-
this._levelsUpdated = this._cubemap ? [[true, true, true, true, true, true]] : [true];
790+
this._levelsUpdated = this.cubemap ? [[true, true, true, true, true, true]] : [true];
776791

777792
this._needsUpload = true;
778793
this._needsMipmapsUpload = this._mipmaps;
@@ -822,7 +837,7 @@ class Texture {
822837
// allocate storage for this mip level
823838
const width = Math.max(1, this._width >> options.level);
824839
const height = Math.max(1, this._height >> options.level);
825-
const depth = Math.max(1, this._depth >> options.level);
840+
const depth = Math.max(1, (this._dimension === TEXTUREDIMENSION_3D ? this._slices : 1) >> options.level);
826841
const data = new ArrayBuffer(TextureUtils.calcLevelGpuSize(width, height, depth, this._format));
827842
levels[options.level] = new (getPixelFormatArrayType(this._format))(data);
828843
}
@@ -845,7 +860,7 @@ class Texture {
845860
let invalid = false;
846861
let width, height;
847862

848-
if (this._cubemap) {
863+
if (this.cubemap) {
849864
if (source[0]) {
850865
// rely on first face sizes
851866
width = source[0].width || 0;
@@ -897,7 +912,7 @@ class Texture {
897912
this._height = 4;
898913

899914
// remove levels
900-
if (this._cubemap) {
915+
if (this.cubemap) {
901916
for (let i = 0; i < 6; i++) {
902917
this._levels[mipLevel][i] = null;
903918
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
@@ -139,7 +139,7 @@ class WebglRenderTarget {
139139
gl.framebufferTexture2D(
140140
gl.FRAMEBUFFER,
141141
attachmentBaseConstant + i,
142-
colorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
142+
colorBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
143143
colorBuffer.impl._glTexture,
144144
0
145145
);
@@ -162,11 +162,11 @@ class WebglRenderTarget {
162162
// Attach
163163
if (target._stencil) {
164164
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT,
165-
depthBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
165+
depthBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
166166
target._depthBuffer.impl._glTexture, 0);
167167
} else {
168168
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
169-
depthBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
169+
depthBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
170170
target._depthBuffer.impl._glTexture, 0);
171171
}
172172
} else if (target._depth) {
@@ -291,7 +291,7 @@ class WebglRenderTarget {
291291
const dstFramebuffer = gl.createFramebuffer();
292292
device.setFramebuffer(dstFramebuffer);
293293
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
294-
colorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
294+
colorBuffer.cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,
295295
colorBuffer.impl._glTexture,
296296
0
297297
);

0 commit comments

Comments
 (0)