Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions packages/dev/core/src/Engines/Native/nativeInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ export interface INativeEngine {
getAttributes(shaderProgram: NativeProgram, attributeNames: string[]): number[];

createTexture(): NativeTexture;
initializeTexture(texture: NativeTexture, width: number, height: number, hasMips: boolean, format: number, renderTarget: boolean, srgb: boolean, samples: number): void;
initializeTexture(
texture: NativeTexture,
width: number,
height: number,
hasMips: boolean,
format: number,
renderTarget: boolean,
srgb: boolean,
samples: number,
isCube?: boolean
): void;
loadTexture(texture: NativeTexture, data: ArrayBufferView, generateMips: boolean, invertY: boolean, srgb: boolean, onSuccess: () => void, onError: () => void): void;
loadRawTexture(texture: NativeTexture, data: ArrayBufferView, width: number, height: number, format: number, generateMips: boolean, invertY: boolean): void;
loadRawTexture2DArray(
Expand Down Expand Up @@ -100,7 +110,8 @@ export interface INativeEngine {
height: number,
generateStencilBuffer: boolean,
generateDepthBuffer: boolean,
samples: number
samples: number,
layer?: number
): NativeFramebuffer;

getRenderWidth(): number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export class NativeRenderTargetWrapper extends RenderTargetWrapper {
private __framebuffer: Nullable<NativeFramebuffer> = null;
// eslint-disable-next-line @typescript-eslint/naming-convention
private __framebufferDepthStencil: Nullable<NativeFramebuffer> = null;
// Per-face framebuffers for cube render targets (index = cube face 0..5).
// eslint-disable-next-line @typescript-eslint/naming-convention
private __framebuffers: Nullable<NativeFramebuffer[]> = null;

public get _framebuffer(): Nullable<NativeFramebuffer> {
return this.__framebuffer;
Expand All @@ -23,6 +26,21 @@ export class NativeRenderTargetWrapper extends RenderTargetWrapper {
this.__framebuffer = framebuffer;
}

public get _framebuffers(): Nullable<NativeFramebuffer[]> {
return this.__framebuffers;
}

public set _framebuffers(framebuffers: Nullable<NativeFramebuffer[]>) {
if (this.__framebuffers) {
for (const framebuffer of this.__framebuffers) {
this._engine._releaseFramebufferObjects(framebuffer);
}
}
this.__framebuffers = framebuffers;
// Keep _framebuffer pointing at face 0 so single-target code paths still work.
this.__framebuffer = framebuffers ? framebuffers[0] : null;
}

public get _framebufferDepthStencil(): Nullable<NativeFramebuffer> {
return this.__framebufferDepthStencil;
}
Expand All @@ -40,7 +58,13 @@ export class NativeRenderTargetWrapper extends RenderTargetWrapper {
}

public override dispose(disposeOnlyFramebuffers = false): void {
this._framebuffer = null;
if (this.__framebuffers) {
// Releases all six per-face framebuffers (face 0 is aliased by __framebuffer, so
// clear that alias here without releasing it again).
this._framebuffers = null;
} else {
this._framebuffer = null;
}
Comment thread
bkaradzic-microsoft marked this conversation as resolved.
this._framebufferDepthStencil = null;

super.dispose(disposeOnlyFramebuffers);
Expand Down
81 changes: 76 additions & 5 deletions packages/dev/core/src/Engines/thinNativeEngine.pure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,76 @@ export class ThinNativeEngine extends ThinEngine {
return rtWrapper;
}

public override createRenderTargetCubeTexture(size: number, options?: RenderTargetCreationOptions): RenderTargetWrapper {
const rtWrapper = this._createHardwareRenderTargetWrapper(false, true, size) as NativeRenderTargetWrapper;

let generateDepthBuffer = true;
let generateStencilBuffer = false;
let generateMipMaps = false;
let type = Constants.TEXTURETYPE_UNSIGNED_BYTE;
let samplingMode = Constants.TEXTURE_TRILINEAR_SAMPLINGMODE;
let format = Constants.TEXTUREFORMAT_RGBA;
let samples = 1;
if (options !== undefined && typeof options === "object") {
generateDepthBuffer = options.generateDepthBuffer ?? true;
generateStencilBuffer = !!options.generateStencilBuffer;
generateMipMaps = !!options.generateMipMaps;
type = options.type ?? Constants.TEXTURETYPE_UNSIGNED_BYTE;
samplingMode = options.samplingMode ?? Constants.TEXTURE_TRILINEAR_SAMPLINGMODE;
format = options.format ?? Constants.TEXTUREFORMAT_RGBA;
samples = options.samples ?? 1;
}

if (type === Constants.TEXTURETYPE_FLOAT && !this._caps.textureFloat) {
type = Constants.TEXTURETYPE_UNSIGNED_BYTE;
Logger.Warn("Float textures are not supported. Type forced to TEXTURETYPE_UNSIGNED_BYTE");
}
Comment thread
bkaradzic-microsoft marked this conversation as resolved.

const texture = new InternalTexture(this, InternalTextureSource.RenderTarget);
texture.isCube = true;
texture.baseWidth = size;
texture.baseHeight = size;
texture.width = size;
texture.height = size;
texture.isReady = true;
texture.samples = samples;
texture.generateMipMaps = generateMipMaps;
texture.samplingMode = samplingMode;
texture.type = type;
texture.format = format;
Comment thread
bkaradzic-microsoft marked this conversation as resolved.

Comment thread
bkaradzic-microsoft marked this conversation as resolved.
const nativeTexture = texture._hardwareTexture!.underlyingResource;
const nativeTextureFormat = getNativeTextureFormat(format, type);
// See the createRenderTargetTexture MSAA/mips note: avoid the mips + samples combo on bgfx.
const hasMips = samples > 1 ? false : generateMipMaps;
this._engine.initializeTexture(nativeTexture, size, size, hasMips, nativeTextureFormat, /*renderTarget*/ true, /*srgb*/ false, samples, /*isCube*/ true);
Comment thread
bkaradzic-microsoft marked this conversation as resolved.
this._setTextureSampling(nativeTexture, getNativeSamplingMode(samplingMode));

// The native engine cannot render to all six faces through one framebuffer, so create one
// framebuffer per face (the C++ side binds the matching cube layer); bindFramebuffer(faceIndex)
// then selects the right one.
const framebuffers: NativeFramebuffer[] = [];
for (let face = 0; face < 6; face++) {
framebuffers.push(this._engine.createFrameBuffer(nativeTexture, size, size, generateStencilBuffer, generateDepthBuffer, samples, face));
}

rtWrapper._framebuffers = framebuffers;
rtWrapper._generateDepthBuffer = generateDepthBuffer;
rtWrapper._generateStencilBuffer = generateStencilBuffer;
rtWrapper._samples = samples;

rtWrapper.setTextures(texture);
Comment thread
bkaradzic-microsoft marked this conversation as resolved.

return rtWrapper;
}

public override generateMipMapsForCubemap(_texture: InternalTexture, _unbind = true): void {
// The WebGL path rebinds gl.TEXTURE_CUBE_MAP and calls gl.generateMipmap; both deref _gl, which is
// null on Native. bgfx auto-generates the mip chain when a render target texture created with mips is
// resolved (the same way 2D RTTs get their mips here -- unBindFramebuffer issues no explicit mipgen),
// so this is a no-op on Native.
}

public override updateRenderTargetTextureSampleCount(rtWrapper: RenderTargetWrapper, samples: number): number {
if (rtWrapper.samples === samples) {
return samples;
Expand Down Expand Up @@ -2426,15 +2496,16 @@ export class ThinNativeEngine extends ThinEngine {

this._currentRenderTarget = texture;

if (faceIndex) {
throw new Error("Cuboid frame buffers are not yet supported in NativeEngine.");
}

if (requiredWidth || requiredHeight) {
throw new Error("Required width/height for frame buffers not yet supported in NativeEngine.");
}

if (nativeRTWrapper._framebufferDepthStencil) {
if (nativeRTWrapper._framebuffers) {
// Cube render target: bind the framebuffer for the requested face.
this._bindUnboundFramebuffer(nativeRTWrapper._framebuffers[faceIndex ?? 0]);
} else if (faceIndex) {
throw new Error("Cuboid frame buffers are not yet supported in NativeEngine.");
} else if (nativeRTWrapper._framebufferDepthStencil) {
this._bindUnboundFramebuffer(nativeRTWrapper._framebufferDepthStencil);
} else {
this._bindUnboundFramebuffer(nativeRTWrapper._framebuffer);
Expand Down
Loading