Vom Anderen PC aus hoch gespielt
This commit is contained in:
274
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js
generated
vendored
Normal file
274
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js
generated
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
import { Float16BufferAttribute } from 'three';
|
||||
import { GPUInputStepMode } from './WebGPUConstants.js';
|
||||
|
||||
const typedArraysToVertexFormatPrefix = new Map( [
|
||||
[ Int8Array, [ 'sint8', 'snorm8' ]],
|
||||
[ Uint8Array, [ 'uint8', 'unorm8' ]],
|
||||
[ Int16Array, [ 'sint16', 'snorm16' ]],
|
||||
[ Uint16Array, [ 'uint16', 'unorm16' ]],
|
||||
[ Int32Array, [ 'sint32', 'snorm32' ]],
|
||||
[ Uint32Array, [ 'uint32', 'unorm32' ]],
|
||||
[ Float32Array, [ 'float32', ]],
|
||||
] );
|
||||
|
||||
const typedAttributeToVertexFormatPrefix = new Map( [
|
||||
[ Float16BufferAttribute, [ 'float16', ]],
|
||||
] );
|
||||
|
||||
const typeArraysToVertexFormatPrefixForItemSize1 = new Map( [
|
||||
[ Int32Array, 'sint32' ],
|
||||
[ Uint32Array, 'uint32' ],
|
||||
[ Float32Array, 'float32' ]
|
||||
] );
|
||||
|
||||
class WebGPUAttributeUtils {
|
||||
|
||||
constructor( backend ) {
|
||||
|
||||
this.backend = backend;
|
||||
|
||||
}
|
||||
|
||||
createAttribute( attribute, usage ) {
|
||||
|
||||
const bufferAttribute = this._getBufferAttribute( attribute );
|
||||
|
||||
const backend = this.backend;
|
||||
const bufferData = backend.get( bufferAttribute );
|
||||
|
||||
let buffer = bufferData.buffer;
|
||||
|
||||
if ( buffer === undefined ) {
|
||||
|
||||
const device = backend.device;
|
||||
|
||||
const array = bufferAttribute.array;
|
||||
const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
|
||||
|
||||
buffer = device.createBuffer( {
|
||||
label: bufferAttribute.name,
|
||||
size: size,
|
||||
usage: usage,
|
||||
mappedAtCreation: true
|
||||
} );
|
||||
|
||||
new array.constructor( buffer.getMappedRange() ).set( array );
|
||||
|
||||
buffer.unmap();
|
||||
|
||||
bufferData.buffer = buffer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateAttribute( attribute ) {
|
||||
|
||||
const bufferAttribute = this._getBufferAttribute( attribute );
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const buffer = backend.get( bufferAttribute ).buffer;
|
||||
|
||||
const array = bufferAttribute.array;
|
||||
const updateRange = bufferAttribute.updateRange;
|
||||
|
||||
if ( updateRange.count === - 1 ) {
|
||||
|
||||
// Not using update ranges
|
||||
|
||||
device.queue.writeBuffer(
|
||||
buffer,
|
||||
0,
|
||||
array,
|
||||
0
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
device.queue.writeBuffer(
|
||||
buffer,
|
||||
0,
|
||||
array,
|
||||
updateRange.offset * array.BYTES_PER_ELEMENT,
|
||||
updateRange.count * array.BYTES_PER_ELEMENT
|
||||
);
|
||||
|
||||
updateRange.count = - 1; // reset range
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
createShaderVertexBuffers( renderObject ) {
|
||||
|
||||
const attributes = renderObject.getAttributes();
|
||||
const vertexBuffers = new Map();
|
||||
|
||||
for ( let slot = 0; slot < attributes.length; slot ++ ) {
|
||||
|
||||
const geometryAttribute = attributes[ slot ];
|
||||
const bytesPerElement = geometryAttribute.array.BYTES_PER_ELEMENT;
|
||||
const bufferAttribute = this._getBufferAttribute( geometryAttribute );
|
||||
|
||||
let vertexBufferLayout = vertexBuffers.get( bufferAttribute );
|
||||
|
||||
if ( vertexBufferLayout === undefined ) {
|
||||
|
||||
let arrayStride, stepMode;
|
||||
|
||||
if ( geometryAttribute.isInterleavedBufferAttribute === true ) {
|
||||
|
||||
arrayStride = geometryAttribute.data.stride * bytesPerElement;
|
||||
stepMode = geometryAttribute.data.isInstancedInterleavedBuffer ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
|
||||
|
||||
} else {
|
||||
|
||||
arrayStride = geometryAttribute.itemSize * bytesPerElement;
|
||||
stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
|
||||
|
||||
}
|
||||
|
||||
vertexBufferLayout = {
|
||||
arrayStride,
|
||||
attributes: [],
|
||||
stepMode
|
||||
};
|
||||
|
||||
vertexBuffers.set( bufferAttribute, vertexBufferLayout );
|
||||
|
||||
}
|
||||
|
||||
const format = this._getVertexFormat( geometryAttribute );
|
||||
const offset = ( geometryAttribute.isInterleavedBufferAttribute === true ) ? geometryAttribute.offset * bytesPerElement : 0;
|
||||
|
||||
vertexBufferLayout.attributes.push( {
|
||||
shaderLocation: slot,
|
||||
offset,
|
||||
format
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
return Array.from( vertexBuffers.values() );
|
||||
|
||||
}
|
||||
|
||||
destroyAttribute( attribute ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const data = backend.get( this._getBufferAttribute( attribute ) );
|
||||
|
||||
data.buffer.destroy();
|
||||
|
||||
backend.delete( attribute );
|
||||
|
||||
}
|
||||
|
||||
async getArrayBufferAsync( attribute ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const data = backend.get( this._getBufferAttribute( attribute ) );
|
||||
|
||||
const bufferGPU = data.buffer;
|
||||
const size = bufferGPU.size;
|
||||
|
||||
let readBufferGPU = data.readBuffer;
|
||||
let needsUnmap = true;
|
||||
|
||||
if ( readBufferGPU === undefined ) {
|
||||
|
||||
readBufferGPU = device.createBuffer( {
|
||||
label: attribute.name,
|
||||
size,
|
||||
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
||||
} );
|
||||
|
||||
needsUnmap = false;
|
||||
|
||||
data.readBuffer = readBufferGPU;
|
||||
|
||||
}
|
||||
|
||||
const cmdEncoder = device.createCommandEncoder( {} );
|
||||
|
||||
cmdEncoder.copyBufferToBuffer(
|
||||
bufferGPU,
|
||||
0,
|
||||
readBufferGPU,
|
||||
0,
|
||||
size
|
||||
);
|
||||
|
||||
if ( needsUnmap ) readBufferGPU.unmap();
|
||||
|
||||
const gpuCommands = cmdEncoder.finish();
|
||||
device.queue.submit( [ gpuCommands ] );
|
||||
|
||||
await readBufferGPU.mapAsync( GPUMapMode.READ );
|
||||
|
||||
const arrayBuffer = readBufferGPU.getMappedRange();
|
||||
|
||||
return arrayBuffer;
|
||||
|
||||
}
|
||||
|
||||
_getVertexFormat( geometryAttribute ) {
|
||||
|
||||
const { itemSize, normalized } = geometryAttribute;
|
||||
const ArrayType = geometryAttribute.array.constructor;
|
||||
const AttributeType = geometryAttribute.constructor;
|
||||
|
||||
let format;
|
||||
|
||||
if ( itemSize == 1 ) {
|
||||
|
||||
format = typeArraysToVertexFormatPrefixForItemSize1.get( ArrayType );
|
||||
|
||||
} else {
|
||||
|
||||
const prefixOptions = typedAttributeToVertexFormatPrefix.get( AttributeType ) || typedArraysToVertexFormatPrefix.get( ArrayType );
|
||||
const prefix = prefixOptions[ normalized ? 1 : 0 ];
|
||||
|
||||
if ( prefix ) {
|
||||
|
||||
const bytesPerUnit = ArrayType.BYTES_PER_ELEMENT * itemSize;
|
||||
const paddedBytesPerUnit = Math.floor( ( bytesPerUnit + 3 ) / 4 ) * 4;
|
||||
const paddedItemSize = paddedBytesPerUnit / ArrayType.BYTES_PER_ELEMENT;
|
||||
|
||||
if ( paddedItemSize % 1 ) {
|
||||
|
||||
throw new Error( 'THREE.WebGPUAttributeUtils: Bad vertex format item size.' );
|
||||
|
||||
}
|
||||
|
||||
format = `${prefix}x${paddedItemSize}`;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! format ) {
|
||||
|
||||
console.error( 'THREE.WebGPUAttributeUtils: Vertex format not supported yet.' );
|
||||
|
||||
}
|
||||
|
||||
return format;
|
||||
|
||||
}
|
||||
|
||||
_getBufferAttribute( attribute ) {
|
||||
|
||||
if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
|
||||
|
||||
return attribute;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUAttributeUtils;
|
||||
236
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js
generated
vendored
Normal file
236
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
import {
|
||||
GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType, GPUTextureSampleType
|
||||
} from './WebGPUConstants.js';
|
||||
import { FloatType } from 'three';
|
||||
|
||||
class WebGPUBindingUtils {
|
||||
|
||||
constructor( backend ) {
|
||||
|
||||
this.backend = backend;
|
||||
|
||||
}
|
||||
|
||||
createBindingsLayout( bindings ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const entries = [];
|
||||
|
||||
let index = 0;
|
||||
|
||||
for ( const binding of bindings ) {
|
||||
|
||||
const bindingGPU = {
|
||||
binding: index ++,
|
||||
visibility: binding.visibility
|
||||
};
|
||||
|
||||
if ( binding.isUniformBuffer || binding.isStorageBuffer ) {
|
||||
|
||||
const buffer = {}; // GPUBufferBindingLayout
|
||||
|
||||
if ( binding.isStorageBuffer ) {
|
||||
|
||||
buffer.type = GPUBufferBindingType.Storage;
|
||||
|
||||
}
|
||||
|
||||
bindingGPU.buffer = buffer;
|
||||
|
||||
} else if ( binding.isSampler ) {
|
||||
|
||||
const sampler = {}; // GPUSamplerBindingLayout
|
||||
|
||||
if ( binding.texture.isDepthTexture ) {
|
||||
|
||||
if ( binding.texture.compareFunction !== null ) {
|
||||
|
||||
sampler.type = 'comparison';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bindingGPU.sampler = sampler;
|
||||
|
||||
} else if ( binding.isSampledTexture && binding.texture.isVideoTexture ) {
|
||||
|
||||
bindingGPU.externalTexture = {}; // GPUExternalTextureBindingLayout
|
||||
|
||||
} else if ( binding.isSampledTexture && binding.store ) {
|
||||
|
||||
const format = this.backend.get( binding.texture ).texture.format;
|
||||
|
||||
bindingGPU.storageTexture = { format }; // GPUStorageTextureBindingLayout
|
||||
|
||||
} else if ( binding.isSampledTexture ) {
|
||||
|
||||
const texture = {}; // GPUTextureBindingLayout
|
||||
|
||||
if ( binding.texture.isDepthTexture ) {
|
||||
|
||||
texture.sampleType = GPUTextureSampleType.Depth;
|
||||
|
||||
} else if ( binding.texture.isDataTexture && binding.texture.type === FloatType ) {
|
||||
|
||||
// @TODO: Add support for this soon: backend.hasFeature( 'float32-filterable' )
|
||||
|
||||
texture.sampleType = GPUTextureSampleType.UnfilterableFloat;
|
||||
|
||||
}
|
||||
|
||||
if ( binding.isSampledCubeTexture ) {
|
||||
|
||||
texture.viewDimension = GPUTextureViewDimension.Cube;
|
||||
|
||||
}
|
||||
|
||||
bindingGPU.texture = texture;
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'WebGPUBindingUtils: Unsupported binding "${ binding }".' );
|
||||
|
||||
}
|
||||
|
||||
entries.push( bindingGPU );
|
||||
|
||||
}
|
||||
|
||||
return device.createBindGroupLayout( { entries } );
|
||||
|
||||
}
|
||||
|
||||
createBindings( bindings ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const bindingsData = backend.get( bindings );
|
||||
|
||||
// setup (static) binding layout and (dynamic) binding group
|
||||
|
||||
const bindLayoutGPU = this.createBindingsLayout( bindings );
|
||||
const bindGroupGPU = this.createBindGroup( bindings, bindLayoutGPU );
|
||||
|
||||
bindingsData.layout = bindLayoutGPU;
|
||||
bindingsData.group = bindGroupGPU;
|
||||
bindingsData.bindings = bindings;
|
||||
|
||||
}
|
||||
|
||||
updateBinding( binding ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const buffer = binding.buffer;
|
||||
const bufferGPU = backend.get( binding ).buffer;
|
||||
|
||||
device.queue.writeBuffer( bufferGPU, 0, buffer, 0 );
|
||||
|
||||
}
|
||||
|
||||
createBindGroup( bindings, layoutGPU ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
let bindingPoint = 0;
|
||||
const entriesGPU = [];
|
||||
|
||||
for ( const binding of bindings ) {
|
||||
|
||||
if ( binding.isUniformBuffer ) {
|
||||
|
||||
const bindingData = backend.get( binding );
|
||||
|
||||
if ( bindingData.buffer === undefined ) {
|
||||
|
||||
const byteLength = binding.byteLength;
|
||||
|
||||
const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
|
||||
|
||||
const bufferGPU = device.createBuffer( {
|
||||
label: 'bindingBuffer',
|
||||
size: byteLength,
|
||||
usage: usage
|
||||
} );
|
||||
|
||||
bindingData.buffer = bufferGPU;
|
||||
|
||||
}
|
||||
|
||||
entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } );
|
||||
|
||||
} else if ( binding.isStorageBuffer ) {
|
||||
|
||||
const bindingData = backend.get( binding );
|
||||
|
||||
if ( bindingData.buffer === undefined ) {
|
||||
|
||||
const attribute = binding.attribute;
|
||||
//const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | /*GPUBufferUsage.COPY_SRC |*/ GPUBufferUsage.COPY_DST;
|
||||
|
||||
//backend.attributeUtils.createAttribute( attribute, usage ); // @TODO: Move it to universal renderer
|
||||
|
||||
bindingData.buffer = backend.get( attribute ).buffer;
|
||||
|
||||
}
|
||||
|
||||
entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } );
|
||||
|
||||
} else if ( binding.isSampler ) {
|
||||
|
||||
const textureGPU = backend.get( binding.texture );
|
||||
|
||||
entriesGPU.push( { binding: bindingPoint, resource: textureGPU.sampler } );
|
||||
|
||||
} else if ( binding.isSampledTexture ) {
|
||||
|
||||
const textureData = backend.get( binding.texture );
|
||||
|
||||
let dimensionViewGPU;
|
||||
|
||||
if ( binding.isSampledCubeTexture ) {
|
||||
|
||||
dimensionViewGPU = GPUTextureViewDimension.Cube;
|
||||
|
||||
} else {
|
||||
|
||||
dimensionViewGPU = GPUTextureViewDimension.TwoD;
|
||||
|
||||
}
|
||||
|
||||
let resourceGPU;
|
||||
|
||||
if ( textureData.externalTexture !== undefined ) {
|
||||
|
||||
resourceGPU = device.importExternalTexture( { source: textureData.externalTexture } );
|
||||
|
||||
} else {
|
||||
|
||||
const aspectGPU = GPUTextureAspect.All;
|
||||
|
||||
resourceGPU = textureData.texture.createView( { aspect: aspectGPU, dimension: dimensionViewGPU } );
|
||||
|
||||
}
|
||||
|
||||
entriesGPU.push( { binding: bindingPoint, resource: resourceGPU } );
|
||||
|
||||
}
|
||||
|
||||
bindingPoint ++;
|
||||
|
||||
}
|
||||
|
||||
return device.createBindGroup( {
|
||||
layout: layoutGPU,
|
||||
entries: entriesGPU
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUBindingUtils;
|
||||
324
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUConstants.js
generated
vendored
Normal file
324
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUConstants.js
generated
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
export const GPUPrimitiveTopology = {
|
||||
PointList: 'point-list',
|
||||
LineList: 'line-list',
|
||||
LineStrip: 'line-strip',
|
||||
TriangleList: 'triangle-list',
|
||||
TriangleStrip: 'triangle-strip',
|
||||
};
|
||||
|
||||
export const GPUCompareFunction = {
|
||||
Never: 'never',
|
||||
Less: 'less',
|
||||
Equal: 'equal',
|
||||
LessEqual: 'less-equal',
|
||||
Greater: 'greater',
|
||||
NotEqual: 'not-equal',
|
||||
GreaterEqual: 'greater-equal',
|
||||
Always: 'always'
|
||||
};
|
||||
|
||||
export const GPUStoreOp = {
|
||||
Store: 'store',
|
||||
Discard: 'discard'
|
||||
};
|
||||
|
||||
export const GPULoadOp = {
|
||||
Load: 'load',
|
||||
Clear: 'clear'
|
||||
};
|
||||
|
||||
export const GPUFrontFace = {
|
||||
CCW: 'ccw',
|
||||
CW: 'cw'
|
||||
};
|
||||
|
||||
export const GPUCullMode = {
|
||||
None: 'none',
|
||||
Front: 'front',
|
||||
Back: 'back'
|
||||
};
|
||||
|
||||
export const GPUIndexFormat = {
|
||||
Uint16: 'uint16',
|
||||
Uint32: 'uint32'
|
||||
};
|
||||
|
||||
export const GPUVertexFormat = {
|
||||
Uint8x2: 'uint8x2',
|
||||
Uint8x4: 'uint8x4',
|
||||
Sint8x2: 'sint8x2',
|
||||
Sint8x4: 'sint8x4',
|
||||
Unorm8x2: 'unorm8x2',
|
||||
Unorm8x4: 'unorm8x4',
|
||||
Snorm8x2: 'snorm8x2',
|
||||
Snorm8x4: 'snorm8x4',
|
||||
Uint16x2: 'uint16x2',
|
||||
Uint16x4: 'uint16x4',
|
||||
Sint16x2: 'sint16x2',
|
||||
Sint16x4: 'sint16x4',
|
||||
Unorm16x2: 'unorm16x2',
|
||||
Unorm16x4: 'unorm16x4',
|
||||
Snorm16x2: 'snorm16x2',
|
||||
Snorm16x4: 'snorm16x4',
|
||||
Float16x2: 'float16x2',
|
||||
Float16x4: 'float16x4',
|
||||
Float32: 'float32',
|
||||
Float32x2: 'float32x2',
|
||||
Float32x3: 'float32x3',
|
||||
Float32x4: 'float32x4',
|
||||
Uint32: 'uint32',
|
||||
Uint32x2: 'uint32x2',
|
||||
Uint32x3: 'uint32x3',
|
||||
Uint32x4: 'uint32x4',
|
||||
Sint32: 'sint32',
|
||||
Sint32x2: 'sint32x2',
|
||||
Sint32x3: 'sint32x3',
|
||||
Sint32x4: 'sint32x4'
|
||||
};
|
||||
|
||||
export const GPUTextureFormat = {
|
||||
|
||||
// 8-bit formats
|
||||
|
||||
R8Unorm: 'r8unorm',
|
||||
R8Snorm: 'r8snorm',
|
||||
R8Uint: 'r8uint',
|
||||
R8Sint: 'r8sint',
|
||||
|
||||
// 16-bit formats
|
||||
|
||||
R16Uint: 'r16uint',
|
||||
R16Sint: 'r16sint',
|
||||
R16Float: 'r16float',
|
||||
RG8Unorm: 'rg8unorm',
|
||||
RG8Snorm: 'rg8snorm',
|
||||
RG8Uint: 'rg8uint',
|
||||
RG8Sint: 'rg8sint',
|
||||
|
||||
// 32-bit formats
|
||||
|
||||
R32Uint: 'r32uint',
|
||||
R32Sint: 'r32sint',
|
||||
R32Float: 'r32float',
|
||||
RG16Uint: 'rg16uint',
|
||||
RG16Sint: 'rg16sint',
|
||||
RG16Float: 'rg16float',
|
||||
RGBA8Unorm: 'rgba8unorm',
|
||||
RGBA8UnormSRGB: 'rgba8unorm-srgb',
|
||||
RGBA8Snorm: 'rgba8snorm',
|
||||
RGBA8Uint: 'rgba8uint',
|
||||
RGBA8Sint: 'rgba8sint',
|
||||
BGRA8Unorm: 'bgra8unorm',
|
||||
BGRA8UnormSRGB: 'bgra8unorm-srgb',
|
||||
// Packed 32-bit formats
|
||||
RGB9E5UFloat: 'rgb9e5ufloat',
|
||||
RGB10A2Unorm: 'rgb10a2unorm',
|
||||
RG11B10uFloat: 'rgb10a2unorm',
|
||||
|
||||
// 64-bit formats
|
||||
|
||||
RG32Uint: 'rg32uint',
|
||||
RG32Sint: 'rg32sint',
|
||||
RG32Float: 'rg32float',
|
||||
RGBA16Uint: 'rgba16uint',
|
||||
RGBA16Sint: 'rgba16sint',
|
||||
RGBA16Float: 'rgba16float',
|
||||
|
||||
// 128-bit formats
|
||||
|
||||
RGBA32Uint: 'rgba32uint',
|
||||
RGBA32Sint: 'rgba32sint',
|
||||
RGBA32Float: 'rgba32float',
|
||||
|
||||
// Depth and stencil formats
|
||||
|
||||
Stencil8: 'stencil8',
|
||||
Depth16Unorm: 'depth16unorm',
|
||||
Depth24Plus: 'depth24plus',
|
||||
Depth24PlusStencil8: 'depth24plus-stencil8',
|
||||
Depth32Float: 'depth32float',
|
||||
|
||||
// 'depth32float-stencil8' extension
|
||||
|
||||
Depth32FloatStencil8: 'depth32float-stencil8',
|
||||
|
||||
// BC compressed formats usable if 'texture-compression-bc' is both
|
||||
// supported by the device/user agent and enabled in requestDevice.
|
||||
|
||||
BC1RGBAUnorm: 'bc1-rgba-unorm',
|
||||
BC1RGBAUnormSRGB: 'bc1-rgba-unorm-srgb',
|
||||
BC2RGBAUnorm: 'bc2-rgba-unorm',
|
||||
BC2RGBAUnormSRGB: 'bc2-rgba-unorm-srgb',
|
||||
BC3RGBAUnorm: 'bc3-rgba-unorm',
|
||||
BC3RGBAUnormSRGB: 'bc3-rgba-unorm-srgb',
|
||||
BC4RUnorm: 'bc4-r-unorm',
|
||||
BC4RSnorm: 'bc4-r-snorm',
|
||||
BC5RGUnorm: 'bc5-rg-unorm',
|
||||
BC5RGSnorm: 'bc5-rg-snorm',
|
||||
BC6HRGBUFloat: 'bc6h-rgb-ufloat',
|
||||
BC6HRGBFloat: 'bc6h-rgb-float',
|
||||
BC7RGBAUnorm: 'bc7-rgba-unorm',
|
||||
BC7RGBAUnormSRGB: 'bc7-rgba-srgb',
|
||||
|
||||
// ETC2 compressed formats usable if 'texture-compression-etc2' is both
|
||||
// supported by the device/user agent and enabled in requestDevice.
|
||||
|
||||
ETC2RGB8Unorm: 'etc2-rgb8unorm',
|
||||
ETC2RGB8UnormSRGB: 'etc2-rgb8unorm-srgb',
|
||||
ETC2RGB8A1Unorm: 'etc2-rgb8a1unorm',
|
||||
ETC2RGB8A1UnormSRGB: 'etc2-rgb8a1unorm-srgb',
|
||||
ETC2RGBA8Unorm: 'etc2-rgba8unorm',
|
||||
ETC2RGBA8UnormSRGB: 'etc2-rgba8unorm-srgb',
|
||||
EACR11Unorm: 'eac-r11unorm',
|
||||
EACR11Snorm: 'eac-r11snorm',
|
||||
EACRG11Unorm: 'eac-rg11unorm',
|
||||
EACRG11Snorm: 'eac-rg11snorm',
|
||||
|
||||
// ASTC compressed formats usable if 'texture-compression-astc' is both
|
||||
// supported by the device/user agent and enabled in requestDevice.
|
||||
|
||||
ASTC4x4Unorm: 'astc-4x4-unorm',
|
||||
ASTC4x4UnormSRGB: 'astc-4x4-unorm-srgb',
|
||||
ASTC5x4Unorm: 'astc-5x4-unorm',
|
||||
ASTC5x4UnormSRGB: 'astc-5x4-unorm-srgb',
|
||||
ASTC5x5Unorm: 'astc-5x5-unorm',
|
||||
ASTC5x5UnormSRGB: 'astc-5x5-unorm-srgb',
|
||||
ASTC6x5Unorm: 'astc-6x5-unorm',
|
||||
ASTC6x5UnormSRGB: 'astc-6x5-unorm-srgb',
|
||||
ASTC6x6Unorm: 'astc-6x6-unorm',
|
||||
ASTC6x6UnormSRGB: 'astc-6x6-unorm-srgb',
|
||||
ASTC8x5Unorm: 'astc-8x5-unorm',
|
||||
ASTC8x5UnormSRGB: 'astc-8x5-unorm-srgb',
|
||||
ASTC8x6Unorm: 'astc-8x6-unorm',
|
||||
ASTC8x6UnormSRGB: 'astc-8x6-unorm-srgb',
|
||||
ASTC8x8Unorm: 'astc-8x8-unorm',
|
||||
ASTC8x8UnormSRGB: 'astc-8x8-unorm-srgb',
|
||||
ASTC10x5Unorm: 'astc-10x5-unorm',
|
||||
ASTC10x5UnormSRGB: 'astc-10x5-unorm-srgb',
|
||||
ASTC10x6Unorm: 'astc-10x6-unorm',
|
||||
ASTC10x6UnormSRGB: 'astc-10x6-unorm-srgb',
|
||||
ASTC10x8Unorm: 'astc-10x8-unorm',
|
||||
ASTC10x8UnormSRGB: 'astc-10x8-unorm-srgb',
|
||||
ASTC10x10Unorm: 'astc-10x10-unorm',
|
||||
ASTC10x10UnormSRGB: 'astc-10x10-unorm-srgb',
|
||||
ASTC12x10Unorm: 'astc-12x10-unorm',
|
||||
ASTC12x10UnormSRGB: 'astc-12x10-unorm-srgb',
|
||||
ASTC12x12Unorm: 'astc-12x12-unorm',
|
||||
ASTC12x12UnormSRGB: 'astc-12x12-unorm-srgb',
|
||||
|
||||
};
|
||||
|
||||
export const GPUAddressMode = {
|
||||
ClampToEdge: 'clamp-to-edge',
|
||||
Repeat: 'repeat',
|
||||
MirrorRepeat: 'mirror-repeat'
|
||||
};
|
||||
|
||||
export const GPUFilterMode = {
|
||||
Linear: 'linear',
|
||||
Nearest: 'nearest'
|
||||
};
|
||||
|
||||
export const GPUBlendFactor = {
|
||||
Zero: 'zero',
|
||||
One: 'one',
|
||||
Src: 'src',
|
||||
OneMinusSrc: 'one-minus-src',
|
||||
SrcAlpha: 'src-alpha',
|
||||
OneMinusSrcAlpha: 'one-minus-src-alpha',
|
||||
Dst: 'dst',
|
||||
OneMinusDstColor: 'one-minus-dst',
|
||||
DstAlpha: 'dst-alpha',
|
||||
OneMinusDstAlpha: 'one-minus-dst-alpha',
|
||||
SrcAlphaSaturated: 'src-alpha-saturated',
|
||||
Constant: 'constant',
|
||||
OneMinusConstant: 'one-minus-constant'
|
||||
};
|
||||
|
||||
export const GPUBlendOperation = {
|
||||
Add: 'add',
|
||||
Subtract: 'subtract',
|
||||
ReverseSubtract: 'reverse-subtract',
|
||||
Min: 'min',
|
||||
Max: 'max'
|
||||
};
|
||||
|
||||
export const GPUColorWriteFlags = {
|
||||
None: 0,
|
||||
Red: 0x1,
|
||||
Green: 0x2,
|
||||
Blue: 0x4,
|
||||
Alpha: 0x8,
|
||||
All: 0xF
|
||||
};
|
||||
|
||||
export const GPUStencilOperation = {
|
||||
Keep: 'keep',
|
||||
Zero: 'zero',
|
||||
Replace: 'replace',
|
||||
Invert: 'invert',
|
||||
IncrementClamp: 'increment-clamp',
|
||||
DecrementClamp: 'decrement-clamp',
|
||||
IncrementWrap: 'increment-wrap',
|
||||
DecrementWrap: 'decrement-wrap'
|
||||
};
|
||||
|
||||
export const GPUBufferBindingType = {
|
||||
Uniform: 'uniform',
|
||||
Storage: 'storage',
|
||||
ReadOnlyStorage: 'read-only-storage'
|
||||
};
|
||||
|
||||
export const GPUSamplerBindingType = {
|
||||
Filtering: 'filtering',
|
||||
NonFiltering: 'non-filtering',
|
||||
Comparison: 'comparison'
|
||||
};
|
||||
|
||||
export const GPUTextureSampleType = {
|
||||
Float: 'float',
|
||||
UnfilterableFloat: 'unfilterable-float',
|
||||
Depth: 'depth',
|
||||
SInt: 'sint',
|
||||
UInt: 'uint'
|
||||
};
|
||||
|
||||
export const GPUTextureDimension = {
|
||||
OneD: '1d',
|
||||
TwoD: '2d',
|
||||
ThreeD: '3d'
|
||||
};
|
||||
|
||||
export const GPUTextureViewDimension = {
|
||||
OneD: '1d',
|
||||
TwoD: '2d',
|
||||
TwoDArray: '2d-array',
|
||||
Cube: 'cube',
|
||||
CubeArray: 'cube-array',
|
||||
ThreeD: '3d'
|
||||
};
|
||||
|
||||
export const GPUTextureAspect = {
|
||||
All: 'all',
|
||||
StencilOnly: 'stencil-only',
|
||||
DepthOnly: 'depth-only'
|
||||
};
|
||||
|
||||
export const GPUInputStepMode = {
|
||||
Vertex: 'vertex',
|
||||
Instance: 'instance'
|
||||
};
|
||||
|
||||
export const GPUFeatureName = {
|
||||
DepthClipControl: 'depth-clip-control',
|
||||
Depth32FloatStencil8: 'depth32float-stencil8',
|
||||
TextureCompressionBC: 'texture-compression-bc',
|
||||
TextureCompressionETC2: 'texture-compression-etc2',
|
||||
TextureCompressionASTC: 'texture-compression-astc',
|
||||
TimestampQuery: 'timestamp-query',
|
||||
IndirectFirstInstance: 'indirect-first-instance',
|
||||
ShaderF16: 'shader-f16',
|
||||
RG11B10UFloat: 'rg11b10ufloat-renderable',
|
||||
BGRA8UNormStorage: 'bgra8unorm-storage',
|
||||
Float32Filterable: 'float32-filterable'
|
||||
};
|
||||
558
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js
generated
vendored
Normal file
558
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js
generated
vendored
Normal file
@@ -0,0 +1,558 @@
|
||||
import { BlendColorFactor, OneMinusBlendColorFactor, } from '../../common/Constants.js';
|
||||
|
||||
import {
|
||||
GPUFrontFace, GPUCullMode, GPUColorWriteFlags, GPUCompareFunction, GPUBlendFactor, GPUBlendOperation, GPUIndexFormat, GPUStencilOperation
|
||||
} from './WebGPUConstants.js';
|
||||
|
||||
import {
|
||||
FrontSide, BackSide, DoubleSide,
|
||||
NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth,
|
||||
NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending,
|
||||
ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstColorFactor,
|
||||
OneMinusDstColorFactor, DstAlphaFactor, OneMinusDstAlphaFactor, SrcAlphaSaturateFactor,
|
||||
AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation,
|
||||
KeepStencilOp, ZeroStencilOp, ReplaceStencilOp, InvertStencilOp, IncrementStencilOp, DecrementStencilOp, IncrementWrapStencilOp, DecrementWrapStencilOp,
|
||||
NeverStencilFunc, AlwaysStencilFunc, LessStencilFunc, LessEqualStencilFunc, EqualStencilFunc, GreaterEqualStencilFunc, GreaterStencilFunc, NotEqualStencilFunc
|
||||
} from 'three';
|
||||
|
||||
class WebGPUPipelineUtils {
|
||||
|
||||
constructor( backend ) {
|
||||
|
||||
this.backend = backend;
|
||||
|
||||
}
|
||||
|
||||
createRenderPipeline( renderObject ) {
|
||||
|
||||
const { object, material, geometry, pipeline } = renderObject;
|
||||
const { vertexProgram, fragmentProgram } = pipeline;
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
const utils = backend.utils;
|
||||
|
||||
const pipelineData = backend.get( pipeline );
|
||||
const bindingsData = backend.get( renderObject.getBindings() );
|
||||
|
||||
// vertex buffers
|
||||
|
||||
const vertexBuffers = backend.attributeUtils.createShaderVertexBuffers( renderObject );
|
||||
|
||||
// blending
|
||||
|
||||
let blending;
|
||||
|
||||
if ( material.transparent === true && material.blending !== NoBlending ) {
|
||||
|
||||
blending = this._getBlending( material );
|
||||
|
||||
}
|
||||
|
||||
// stencil
|
||||
|
||||
let stencilFront = {};
|
||||
|
||||
if ( material.stencilWrite === true ) {
|
||||
|
||||
stencilFront = {
|
||||
compare: this._getStencilCompare( material ),
|
||||
failOp: this._getStencilOperation( material.stencilFail ),
|
||||
depthFailOp: this._getStencilOperation( material.stencilZFail ),
|
||||
passOp: this._getStencilOperation( material.stencilZPass )
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const colorWriteMask = this._getColorWriteMask( material );
|
||||
|
||||
const targets = [];
|
||||
|
||||
if ( renderObject.context.textures !== null ) {
|
||||
|
||||
const textures = renderObject.context.textures;
|
||||
|
||||
for ( let i = 0; i < textures.length; i ++ ) {
|
||||
|
||||
const colorFormat = utils.getTextureFormatGPU( textures[ i ] );
|
||||
|
||||
targets.push( {
|
||||
format: colorFormat,
|
||||
blend: blending,
|
||||
writeMask: colorWriteMask
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
const colorFormat = utils.getCurrentColorFormat( renderObject.context );
|
||||
|
||||
targets.push( {
|
||||
format: colorFormat,
|
||||
blend: blending,
|
||||
writeMask: colorWriteMask
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
const vertexModule = backend.get( vertexProgram ).module;
|
||||
const fragmentModule = backend.get( fragmentProgram ).module;
|
||||
|
||||
const primitiveState = this._getPrimitiveState( object, geometry, material );
|
||||
const depthCompare = this._getDepthCompare( material );
|
||||
const depthStencilFormat = utils.getCurrentDepthStencilFormat( renderObject.context );
|
||||
const sampleCount = utils.getSampleCount( renderObject.context );
|
||||
|
||||
pipelineData.pipeline = device.createRenderPipeline( {
|
||||
vertex: Object.assign( {}, vertexModule, { buffers: vertexBuffers } ),
|
||||
fragment: Object.assign( {}, fragmentModule, { targets } ),
|
||||
primitive: primitiveState,
|
||||
depthStencil: {
|
||||
format: depthStencilFormat,
|
||||
depthWriteEnabled: material.depthWrite,
|
||||
depthCompare: depthCompare,
|
||||
stencilFront: stencilFront,
|
||||
stencilBack: {}, // three.js does not provide an API to configure the back function (gl.stencilFuncSeparate() was never used)
|
||||
stencilReadMask: material.stencilFuncMask,
|
||||
stencilWriteMask: material.stencilWriteMask
|
||||
},
|
||||
multisample: {
|
||||
count: sampleCount,
|
||||
alphaToCoverageEnabled: material.alphaToCoverage
|
||||
},
|
||||
layout: device.createPipelineLayout( {
|
||||
bindGroupLayouts: [ bindingsData.layout ]
|
||||
} )
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
createComputePipeline( pipeline, bindings ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const computeProgram = backend.get( pipeline.computeProgram ).module;
|
||||
|
||||
const pipelineGPU = backend.get( pipeline );
|
||||
const bindingsData = backend.get( bindings );
|
||||
|
||||
pipelineGPU.pipeline = device.createComputePipeline( {
|
||||
compute: computeProgram,
|
||||
layout: device.createPipelineLayout( {
|
||||
bindGroupLayouts: [ bindingsData.layout ]
|
||||
} )
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_getBlending( material ) {
|
||||
|
||||
let color, alpha;
|
||||
|
||||
const blending = material.blending;
|
||||
|
||||
if ( blending === CustomBlending ) {
|
||||
|
||||
const blendSrcAlpha = material.blendSrcAlpha !== null ? material.blendSrcAlpha : GPUBlendFactor.One;
|
||||
const blendDstAlpha = material.blendDstAlpha !== null ? material.blendDstAlpha : GPUBlendFactor.Zero;
|
||||
const blendEquationAlpha = material.blendEquationAlpha !== null ? material.blendEquationAlpha : GPUBlendFactor.Add;
|
||||
|
||||
color = {
|
||||
srcFactor: this._getBlendFactor( material.blendSrc ),
|
||||
dstFactor: this._getBlendFactor( material.blendDst ),
|
||||
operation: this._getBlendOperation( material.blendEquation )
|
||||
};
|
||||
|
||||
alpha = {
|
||||
srcFactor: this._getBlendFactor( blendSrcAlpha ),
|
||||
dstFactor: this._getBlendFactor( blendDstAlpha ),
|
||||
operation: this._getBlendOperation( blendEquationAlpha )
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
const premultipliedAlpha = material.premultipliedAlpha;
|
||||
|
||||
const setBlend = ( srcRGB, dstRGB, srcAlpha, dstAlpha ) => {
|
||||
|
||||
color = {
|
||||
srcFactor: srcRGB,
|
||||
dstFactor: dstRGB,
|
||||
operation: GPUBlendOperation.Add
|
||||
};
|
||||
|
||||
alpha = {
|
||||
srcFactor: srcAlpha,
|
||||
dstFactor: dstAlpha,
|
||||
operation: GPUBlendOperation.Add
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
if ( premultipliedAlpha ) {
|
||||
|
||||
switch ( blending ) {
|
||||
|
||||
case NormalBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha );
|
||||
break;
|
||||
|
||||
case AdditiveBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case SubtractiveBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case MultiplyBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.SrcAlpha );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
switch ( blending ) {
|
||||
|
||||
case NormalBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha );
|
||||
break;
|
||||
|
||||
case AdditiveBlending:
|
||||
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.SrcAlpha, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case SubtractiveBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One );
|
||||
break;
|
||||
|
||||
case MultiplyBlending:
|
||||
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.Src );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( color !== undefined && alpha !== undefined ) {
|
||||
|
||||
return { color, alpha };
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'THREE.WebGPURenderer: Invalid blending: ', blending );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_getBlendFactor( blend ) {
|
||||
|
||||
let blendFactor;
|
||||
|
||||
switch ( blend ) {
|
||||
|
||||
case ZeroFactor:
|
||||
blendFactor = GPUBlendFactor.Zero;
|
||||
break;
|
||||
|
||||
case OneFactor:
|
||||
blendFactor = GPUBlendFactor.One;
|
||||
break;
|
||||
|
||||
case SrcColorFactor:
|
||||
blendFactor = GPUBlendFactor.Src;
|
||||
break;
|
||||
|
||||
case OneMinusSrcColorFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusSrc;
|
||||
break;
|
||||
|
||||
case SrcAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.SrcAlpha;
|
||||
break;
|
||||
|
||||
case OneMinusSrcAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusSrcAlpha;
|
||||
break;
|
||||
|
||||
case DstColorFactor:
|
||||
blendFactor = GPUBlendFactor.Dst;
|
||||
break;
|
||||
|
||||
case OneMinusDstColorFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusDstColor;
|
||||
break;
|
||||
|
||||
case DstAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.DstAlpha;
|
||||
break;
|
||||
|
||||
case OneMinusDstAlphaFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusDstAlpha;
|
||||
break;
|
||||
|
||||
case SrcAlphaSaturateFactor:
|
||||
blendFactor = GPUBlendFactor.SrcAlphaSaturated;
|
||||
break;
|
||||
|
||||
case BlendColorFactor:
|
||||
blendFactor = GPUBlendFactor.Constant;
|
||||
break;
|
||||
|
||||
case OneMinusBlendColorFactor:
|
||||
blendFactor = GPUBlendFactor.OneMinusConstant;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPURenderer: Blend factor not supported.', blend );
|
||||
|
||||
}
|
||||
|
||||
return blendFactor;
|
||||
|
||||
}
|
||||
|
||||
_getStencilCompare( material ) {
|
||||
|
||||
let stencilCompare;
|
||||
|
||||
const stencilFunc = material.stencilFunc;
|
||||
|
||||
switch ( stencilFunc ) {
|
||||
|
||||
case NeverStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Never;
|
||||
break;
|
||||
|
||||
case AlwaysStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Always;
|
||||
break;
|
||||
|
||||
case LessStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Less;
|
||||
break;
|
||||
|
||||
case LessEqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.LessEqual;
|
||||
break;
|
||||
|
||||
case EqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Equal;
|
||||
break;
|
||||
|
||||
case GreaterEqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.GreaterEqual;
|
||||
break;
|
||||
|
||||
case GreaterStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.Greater;
|
||||
break;
|
||||
|
||||
case NotEqualStencilFunc:
|
||||
stencilCompare = GPUCompareFunction.NotEqual;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPURenderer: Invalid stencil function.', stencilFunc );
|
||||
|
||||
}
|
||||
|
||||
return stencilCompare;
|
||||
|
||||
}
|
||||
|
||||
_getStencilOperation( op ) {
|
||||
|
||||
let stencilOperation;
|
||||
|
||||
switch ( op ) {
|
||||
|
||||
case KeepStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Keep;
|
||||
break;
|
||||
|
||||
case ZeroStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Zero;
|
||||
break;
|
||||
|
||||
case ReplaceStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Replace;
|
||||
break;
|
||||
|
||||
case InvertStencilOp:
|
||||
stencilOperation = GPUStencilOperation.Invert;
|
||||
break;
|
||||
|
||||
case IncrementStencilOp:
|
||||
stencilOperation = GPUStencilOperation.IncrementClamp;
|
||||
break;
|
||||
|
||||
case DecrementStencilOp:
|
||||
stencilOperation = GPUStencilOperation.DecrementClamp;
|
||||
break;
|
||||
|
||||
case IncrementWrapStencilOp:
|
||||
stencilOperation = GPUStencilOperation.IncrementWrap;
|
||||
break;
|
||||
|
||||
case DecrementWrapStencilOp:
|
||||
stencilOperation = GPUStencilOperation.DecrementWrap;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPURenderer: Invalid stencil operation.', stencilOperation );
|
||||
|
||||
}
|
||||
|
||||
return stencilOperation;
|
||||
|
||||
}
|
||||
|
||||
_getBlendOperation( blendEquation ) {
|
||||
|
||||
let blendOperation;
|
||||
|
||||
switch ( blendEquation ) {
|
||||
|
||||
case AddEquation:
|
||||
blendOperation = GPUBlendOperation.Add;
|
||||
break;
|
||||
|
||||
case SubtractEquation:
|
||||
blendOperation = GPUBlendOperation.Subtract;
|
||||
break;
|
||||
|
||||
case ReverseSubtractEquation:
|
||||
blendOperation = GPUBlendOperation.ReverseSubtract;
|
||||
break;
|
||||
|
||||
case MinEquation:
|
||||
blendOperation = GPUBlendOperation.Min;
|
||||
break;
|
||||
|
||||
case MaxEquation:
|
||||
blendOperation = GPUBlendOperation.Max;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPUPipelineUtils: Blend equation not supported.', blendEquation );
|
||||
|
||||
}
|
||||
|
||||
return blendOperation;
|
||||
|
||||
}
|
||||
|
||||
_getPrimitiveState( object, geometry, material ) {
|
||||
|
||||
const descriptor = {};
|
||||
const utils = this.backend.utils;
|
||||
|
||||
descriptor.topology = utils.getPrimitiveTopology( object, material );
|
||||
|
||||
if ( object.isLine === true && object.isLineSegments !== true ) {
|
||||
|
||||
const count = ( geometry.index ) ? geometry.index.count : geometry.attributes.position.count;
|
||||
descriptor.stripIndexFormat = ( count > 65535 ) ? GPUIndexFormat.Uint32 : GPUIndexFormat.Uint16; // define data type for primitive restart value
|
||||
|
||||
}
|
||||
|
||||
switch ( material.side ) {
|
||||
|
||||
case FrontSide:
|
||||
descriptor.frontFace = GPUFrontFace.CCW;
|
||||
descriptor.cullMode = GPUCullMode.Back;
|
||||
break;
|
||||
|
||||
case BackSide:
|
||||
descriptor.frontFace = GPUFrontFace.CCW;
|
||||
descriptor.cullMode = GPUCullMode.Front;
|
||||
break;
|
||||
|
||||
case DoubleSide:
|
||||
descriptor.frontFace = GPUFrontFace.CCW;
|
||||
descriptor.cullMode = GPUCullMode.None;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPUPipelineUtils: Unknown material.side value.', material.side );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
|
||||
}
|
||||
|
||||
_getColorWriteMask( material ) {
|
||||
|
||||
return ( material.colorWrite === true ) ? GPUColorWriteFlags.All : GPUColorWriteFlags.None;
|
||||
|
||||
}
|
||||
|
||||
_getDepthCompare( material ) {
|
||||
|
||||
let depthCompare;
|
||||
|
||||
if ( material.depthTest === false ) {
|
||||
|
||||
depthCompare = GPUCompareFunction.Always;
|
||||
|
||||
} else {
|
||||
|
||||
const depthFunc = material.depthFunc;
|
||||
|
||||
switch ( depthFunc ) {
|
||||
|
||||
case NeverDepth:
|
||||
depthCompare = GPUCompareFunction.Never;
|
||||
break;
|
||||
|
||||
case AlwaysDepth:
|
||||
depthCompare = GPUCompareFunction.Always;
|
||||
break;
|
||||
|
||||
case LessDepth:
|
||||
depthCompare = GPUCompareFunction.Less;
|
||||
break;
|
||||
|
||||
case LessEqualDepth:
|
||||
depthCompare = GPUCompareFunction.LessEqual;
|
||||
break;
|
||||
|
||||
case EqualDepth:
|
||||
depthCompare = GPUCompareFunction.Equal;
|
||||
break;
|
||||
|
||||
case GreaterEqualDepth:
|
||||
depthCompare = GPUCompareFunction.GreaterEqual;
|
||||
break;
|
||||
|
||||
case GreaterDepth:
|
||||
depthCompare = GPUCompareFunction.Greater;
|
||||
break;
|
||||
|
||||
case NotEqualDepth:
|
||||
depthCompare = GPUCompareFunction.NotEqual;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'THREE.WebGPUPipelineUtils: Invalid depth function.', depthFunc );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return depthCompare;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUPipelineUtils;
|
||||
285
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUTexturePassUtils.js
generated
vendored
Normal file
285
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUTexturePassUtils.js
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
import { GPUTextureViewDimension, GPUIndexFormat, GPUFilterMode, GPUPrimitiveTopology, GPULoadOp, GPUStoreOp } from './WebGPUConstants.js';
|
||||
|
||||
class WebGPUTexturePassUtils {
|
||||
|
||||
constructor( device ) {
|
||||
|
||||
this.device = device;
|
||||
|
||||
const mipmapVertexSource = `
|
||||
struct VarysStruct {
|
||||
@builtin( position ) Position: vec4<f32>,
|
||||
@location( 0 ) vTex : vec2<f32>
|
||||
};
|
||||
|
||||
@vertex
|
||||
fn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {
|
||||
|
||||
var Varys : VarysStruct;
|
||||
|
||||
var pos = array< vec2<f32>, 4 >(
|
||||
vec2<f32>( -1.0, 1.0 ),
|
||||
vec2<f32>( 1.0, 1.0 ),
|
||||
vec2<f32>( -1.0, -1.0 ),
|
||||
vec2<f32>( 1.0, -1.0 )
|
||||
);
|
||||
|
||||
var tex = array< vec2<f32>, 4 >(
|
||||
vec2<f32>( 0.0, 0.0 ),
|
||||
vec2<f32>( 1.0, 0.0 ),
|
||||
vec2<f32>( 0.0, 1.0 ),
|
||||
vec2<f32>( 1.0, 1.0 )
|
||||
);
|
||||
|
||||
Varys.vTex = tex[ vertexIndex ];
|
||||
Varys.Position = vec4<f32>( pos[ vertexIndex ], 0.0, 1.0 );
|
||||
|
||||
return Varys;
|
||||
|
||||
}
|
||||
`;
|
||||
|
||||
const mipmapFragmentSource = `
|
||||
@group( 0 ) @binding( 0 )
|
||||
var imgSampler : sampler;
|
||||
|
||||
@group( 0 ) @binding( 1 )
|
||||
var img : texture_2d<f32>;
|
||||
|
||||
@fragment
|
||||
fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
|
||||
|
||||
return textureSample( img, imgSampler, vTex );
|
||||
|
||||
}
|
||||
`;
|
||||
|
||||
const flipYFragmentSource = `
|
||||
@group( 0 ) @binding( 0 )
|
||||
var imgSampler : sampler;
|
||||
|
||||
@group( 0 ) @binding( 1 )
|
||||
var img : texture_2d<f32>;
|
||||
|
||||
@fragment
|
||||
fn main( @location( 0 ) vTex : vec2<f32> ) -> @location( 0 ) vec4<f32> {
|
||||
|
||||
return textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );
|
||||
|
||||
}
|
||||
`;
|
||||
this.mipmapSampler = device.createSampler( { minFilter: GPUFilterMode.Linear } );
|
||||
this.flipYSampler = device.createSampler( { minFilter: GPUFilterMode.Nearest } ); //@TODO?: Consider using textureLoad()
|
||||
|
||||
// We'll need a new pipeline for every texture format used.
|
||||
this.transferPipelines = {};
|
||||
this.flipYPipelines = {};
|
||||
|
||||
this.mipmapVertexShaderModule = device.createShaderModule( {
|
||||
label: 'mipmapVertex',
|
||||
code: mipmapVertexSource
|
||||
} );
|
||||
|
||||
this.mipmapFragmentShaderModule = device.createShaderModule( {
|
||||
label: 'mipmapFragment',
|
||||
code: mipmapFragmentSource
|
||||
} );
|
||||
|
||||
this.flipYFragmentShaderModule = device.createShaderModule( {
|
||||
label: 'flipYFragment',
|
||||
code: flipYFragmentSource
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
getTransferPipeline( format ) {
|
||||
|
||||
let pipeline = this.transferPipelines[ format ];
|
||||
|
||||
if ( pipeline === undefined ) {
|
||||
|
||||
pipeline = this.device.createRenderPipeline( {
|
||||
vertex: {
|
||||
module: this.mipmapVertexShaderModule,
|
||||
entryPoint: 'main'
|
||||
},
|
||||
fragment: {
|
||||
module: this.mipmapFragmentShaderModule,
|
||||
entryPoint: 'main',
|
||||
targets: [ { format } ]
|
||||
},
|
||||
primitive: {
|
||||
topology: GPUPrimitiveTopology.TriangleStrip,
|
||||
stripIndexFormat: GPUIndexFormat.Uint32
|
||||
},
|
||||
layout: 'auto'
|
||||
} );
|
||||
|
||||
this.transferPipelines[ format ] = pipeline;
|
||||
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
|
||||
}
|
||||
|
||||
getFlipYPipeline( format ) {
|
||||
|
||||
let pipeline = this.flipYPipelines[ format ];
|
||||
|
||||
if ( pipeline === undefined ) {
|
||||
|
||||
pipeline = this.device.createRenderPipeline( {
|
||||
vertex: {
|
||||
module: this.mipmapVertexShaderModule,
|
||||
entryPoint: 'main'
|
||||
},
|
||||
fragment: {
|
||||
module: this.flipYFragmentShaderModule,
|
||||
entryPoint: 'main',
|
||||
targets: [ { format } ]
|
||||
},
|
||||
primitive: {
|
||||
topology: GPUPrimitiveTopology.TriangleStrip,
|
||||
stripIndexFormat: GPUIndexFormat.Uint32
|
||||
},
|
||||
layout: 'auto'
|
||||
} );
|
||||
|
||||
this.flipYPipelines[ format ] = pipeline;
|
||||
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
|
||||
}
|
||||
|
||||
flipY( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) {
|
||||
|
||||
const format = textureGPUDescriptor.format;
|
||||
const { width, height } = textureGPUDescriptor.size;
|
||||
|
||||
const transferPipeline = this.getTransferPipeline( format );
|
||||
const flipYPipeline = this.getFlipYPipeline( format );
|
||||
|
||||
const tempTexture = this.device.createTexture( {
|
||||
size: { width, height, depthOrArrayLayers: 1 },
|
||||
format,
|
||||
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
|
||||
} );
|
||||
|
||||
const srcView = textureGPU.createView( {
|
||||
baseMipLevel: 0,
|
||||
mipLevelCount: 1,
|
||||
dimension: GPUTextureViewDimension.TwoD,
|
||||
baseArrayLayer
|
||||
} );
|
||||
|
||||
const dstView = tempTexture.createView( {
|
||||
baseMipLevel: 0,
|
||||
mipLevelCount: 1,
|
||||
dimension: GPUTextureViewDimension.TwoD,
|
||||
baseArrayLayer: 0
|
||||
} );
|
||||
|
||||
const commandEncoder = this.device.createCommandEncoder( {} );
|
||||
|
||||
const pass = ( pipeline, sourceView, destinationView ) => {
|
||||
|
||||
const bindGroupLayout = pipeline.getBindGroupLayout( 0 ); // @TODO: Consider making this static.
|
||||
|
||||
const bindGroup = this.device.createBindGroup( {
|
||||
layout: bindGroupLayout,
|
||||
entries: [ {
|
||||
binding: 0,
|
||||
resource: this.flipYSampler
|
||||
}, {
|
||||
binding: 1,
|
||||
resource: sourceView
|
||||
} ]
|
||||
} );
|
||||
|
||||
const passEncoder = commandEncoder.beginRenderPass( {
|
||||
colorAttachments: [ {
|
||||
view: destinationView,
|
||||
loadOp: GPULoadOp.Clear,
|
||||
storeOp: GPUStoreOp.Store,
|
||||
clearValue: [ 0, 0, 0, 0 ]
|
||||
} ]
|
||||
} );
|
||||
|
||||
passEncoder.setPipeline( pipeline );
|
||||
passEncoder.setBindGroup( 0, bindGroup );
|
||||
passEncoder.draw( 4, 1, 0, 0 );
|
||||
passEncoder.end();
|
||||
|
||||
};
|
||||
|
||||
pass( transferPipeline, srcView, dstView );
|
||||
pass( flipYPipeline, dstView, srcView );
|
||||
|
||||
this.device.queue.submit( [ commandEncoder.finish() ] );
|
||||
|
||||
tempTexture.destroy();
|
||||
|
||||
}
|
||||
|
||||
generateMipmaps( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) {
|
||||
|
||||
const pipeline = this.getTransferPipeline( textureGPUDescriptor.format );
|
||||
|
||||
const commandEncoder = this.device.createCommandEncoder( {} );
|
||||
const bindGroupLayout = pipeline.getBindGroupLayout( 0 ); // @TODO: Consider making this static.
|
||||
|
||||
let srcView = textureGPU.createView( {
|
||||
baseMipLevel: 0,
|
||||
mipLevelCount: 1,
|
||||
dimension: GPUTextureViewDimension.TwoD,
|
||||
baseArrayLayer
|
||||
} );
|
||||
|
||||
for ( let i = 1; i < textureGPUDescriptor.mipLevelCount; i ++ ) {
|
||||
|
||||
const bindGroup = this.device.createBindGroup( {
|
||||
layout: bindGroupLayout,
|
||||
entries: [ {
|
||||
binding: 0,
|
||||
resource: this.mipmapSampler
|
||||
}, {
|
||||
binding: 1,
|
||||
resource: srcView
|
||||
} ]
|
||||
} );
|
||||
|
||||
const dstView = textureGPU.createView( {
|
||||
baseMipLevel: i,
|
||||
mipLevelCount: 1,
|
||||
dimension: GPUTextureViewDimension.TwoD,
|
||||
baseArrayLayer
|
||||
} );
|
||||
|
||||
const passEncoder = commandEncoder.beginRenderPass( {
|
||||
colorAttachments: [ {
|
||||
view: dstView,
|
||||
loadOp: GPULoadOp.Clear,
|
||||
storeOp: GPUStoreOp.Store,
|
||||
clearValue: [ 0, 0, 0, 0 ]
|
||||
} ]
|
||||
} );
|
||||
|
||||
passEncoder.setPipeline( pipeline );
|
||||
passEncoder.setBindGroup( 0, bindGroup );
|
||||
passEncoder.draw( 4, 1, 0, 0 );
|
||||
passEncoder.end();
|
||||
|
||||
srcView = dstView;
|
||||
|
||||
}
|
||||
|
||||
this.device.queue.submit( [ commandEncoder.finish() ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUTexturePassUtils;
|
||||
885
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js
generated
vendored
Normal file
885
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js
generated
vendored
Normal file
@@ -0,0 +1,885 @@
|
||||
import {
|
||||
GPUTextureFormat, GPUAddressMode, GPUFilterMode, GPUTextureDimension, GPUFeatureName
|
||||
} from './WebGPUConstants.js';
|
||||
|
||||
import {
|
||||
CubeTexture, Texture,
|
||||
NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter,
|
||||
RepeatWrapping, MirroredRepeatWrapping,
|
||||
RGB_ETC2_Format, RGBA_ETC2_EAC_Format,
|
||||
RGBAFormat, RedFormat, RGFormat, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, UnsignedByteType, FloatType, HalfFloatType, SRGBColorSpace, DepthFormat, DepthStencilFormat,
|
||||
RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format,
|
||||
RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, UnsignedIntType, UnsignedShortType, UnsignedInt248Type,
|
||||
NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare
|
||||
} from 'three';
|
||||
|
||||
import { CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from 'three';
|
||||
|
||||
import WebGPUTexturePassUtils from './WebGPUTexturePassUtils.js';
|
||||
|
||||
const _compareToWebGPU = {
|
||||
[ NeverCompare ]: 'never',
|
||||
[ LessCompare ]: 'less',
|
||||
[ EqualCompare ]: 'equal',
|
||||
[ LessEqualCompare ]: 'less-equal',
|
||||
[ GreaterCompare ]: 'greater',
|
||||
[ GreaterEqualCompare ]: 'greater-equal',
|
||||
[ AlwaysCompare ]: 'always',
|
||||
[ NotEqualCompare ]: 'not-equal'
|
||||
};
|
||||
|
||||
const _flipMap = [ 0, 1, 3, 2, 4, 5 ];
|
||||
|
||||
class WebGPUTextureUtils {
|
||||
|
||||
constructor( backend ) {
|
||||
|
||||
this.backend = backend;
|
||||
|
||||
this._passUtils = null;
|
||||
|
||||
this.defaultTexture = null;
|
||||
this.defaultCubeTexture = null;
|
||||
|
||||
}
|
||||
|
||||
createSampler( texture ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const device = backend.device;
|
||||
|
||||
const textureGPU = backend.get( texture );
|
||||
|
||||
const samplerDescriptorGPU = {
|
||||
addressModeU: this._convertAddressMode( texture.wrapS ),
|
||||
addressModeV: this._convertAddressMode( texture.wrapT ),
|
||||
addressModeW: this._convertAddressMode( texture.wrapR ),
|
||||
magFilter: this._convertFilterMode( texture.magFilter ),
|
||||
minFilter: this._convertFilterMode( texture.minFilter ),
|
||||
mipmapFilter: this._convertFilterMode( texture.minFilter ),
|
||||
maxAnisotropy: texture.anisotropy
|
||||
};
|
||||
|
||||
if ( texture.isDepthTexture && texture.compareFunction !== null ) {
|
||||
|
||||
samplerDescriptorGPU.compare = _compareToWebGPU[ texture.compareFunction ];
|
||||
|
||||
}
|
||||
|
||||
textureGPU.sampler = device.createSampler( samplerDescriptorGPU );
|
||||
|
||||
}
|
||||
|
||||
createDefaultTexture( texture ) {
|
||||
|
||||
let textureGPU;
|
||||
|
||||
if ( texture.isCubeTexture ) {
|
||||
|
||||
textureGPU = this._getDefaultCubeTextureGPU();
|
||||
|
||||
} else {
|
||||
|
||||
textureGPU = this._getDefaultTextureGPU();
|
||||
|
||||
}
|
||||
|
||||
this.backend.get( texture ).texture = textureGPU;
|
||||
|
||||
}
|
||||
|
||||
createTexture( texture, options = {} ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const textureData = backend.get( texture );
|
||||
|
||||
if ( textureData.initialized ) {
|
||||
|
||||
throw new Error( 'WebGPUTextureUtils: Texture already initialized.' );
|
||||
|
||||
}
|
||||
|
||||
if ( options.needsMipmaps === undefined ) options.needsMipmaps = false;
|
||||
if ( options.levels === undefined ) options.levels = 1;
|
||||
if ( options.depth === undefined ) options.depth = 1;
|
||||
|
||||
const { width, height, depth, levels } = options;
|
||||
|
||||
const dimension = this._getDimension( texture );
|
||||
const format = texture.internalFormat || getFormat( texture, this.device );
|
||||
|
||||
const sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1;
|
||||
const primarySampleCount = texture.isRenderTargetTexture ? 1 : sampleCount;
|
||||
|
||||
let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;
|
||||
|
||||
if ( texture.isStorageTexture === true ) {
|
||||
|
||||
usage |= GPUTextureUsage.STORAGE_BINDING;
|
||||
|
||||
}
|
||||
|
||||
if ( texture.isCompressedTexture !== true ) {
|
||||
|
||||
usage |= GPUTextureUsage.RENDER_ATTACHMENT;
|
||||
|
||||
}
|
||||
|
||||
const textureDescriptorGPU = {
|
||||
label: texture.name,
|
||||
size: {
|
||||
width: width,
|
||||
height: height,
|
||||
depthOrArrayLayers: depth,
|
||||
},
|
||||
mipLevelCount: levels,
|
||||
sampleCount: primarySampleCount,
|
||||
dimension: dimension,
|
||||
format: format,
|
||||
usage: usage
|
||||
};
|
||||
|
||||
// texture creation
|
||||
|
||||
if ( texture.isVideoTexture ) {
|
||||
|
||||
const video = texture.source.data;
|
||||
const videoFrame = new VideoFrame( video );
|
||||
|
||||
textureDescriptorGPU.size.width = videoFrame.displayWidth;
|
||||
textureDescriptorGPU.size.height = videoFrame.displayHeight;
|
||||
|
||||
videoFrame.close();
|
||||
|
||||
textureData.externalTexture = video;
|
||||
|
||||
} else {
|
||||
|
||||
if ( format === undefined ) {
|
||||
|
||||
console.warn( 'WebGPURenderer: Texture format not supported.' );
|
||||
|
||||
return this.createDefaultTexture( texture );
|
||||
|
||||
}
|
||||
|
||||
textureData.texture = backend.device.createTexture( textureDescriptorGPU );
|
||||
|
||||
}
|
||||
|
||||
if ( texture.isRenderTargetTexture && sampleCount > 1 ) {
|
||||
|
||||
const msaaTextureDescriptorGPU = Object.assign( {}, textureDescriptorGPU );
|
||||
|
||||
msaaTextureDescriptorGPU.label = msaaTextureDescriptorGPU.label + '-msaa';
|
||||
msaaTextureDescriptorGPU.sampleCount = sampleCount;
|
||||
|
||||
textureData.msaaTexture = backend.device.createTexture( msaaTextureDescriptorGPU );
|
||||
|
||||
}
|
||||
|
||||
textureData.initialized = true;
|
||||
|
||||
textureData.textureDescriptorGPU = textureDescriptorGPU;
|
||||
|
||||
}
|
||||
|
||||
destroyTexture( texture ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const textureData = backend.get( texture );
|
||||
|
||||
textureData.texture.destroy();
|
||||
|
||||
if ( textureData.msaaTexture !== undefined ) textureData.msaaTexture.destroy();
|
||||
|
||||
backend.delete( texture );
|
||||
|
||||
}
|
||||
|
||||
destroySampler( texture ) {
|
||||
|
||||
const backend = this.backend;
|
||||
const textureData = backend.get( texture );
|
||||
|
||||
delete textureData.sampler;
|
||||
|
||||
}
|
||||
|
||||
generateMipmaps( texture ) {
|
||||
|
||||
const textureData = this.backend.get( texture );
|
||||
|
||||
if ( texture.isCubeTexture ) {
|
||||
|
||||
for ( let i = 0; i < 6; i ++ ) {
|
||||
|
||||
this._generateMipmaps( textureData.texture, textureData.textureDescriptorGPU, i );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
this._generateMipmaps( textureData.texture, textureData.textureDescriptorGPU );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateTexture( texture, options ) {
|
||||
|
||||
const textureData = this.backend.get( texture );
|
||||
|
||||
const { textureDescriptorGPU } = textureData;
|
||||
|
||||
if ( texture.isRenderTargetTexture || ( textureDescriptorGPU === undefined /* unsupported texture format */ ) )
|
||||
return;
|
||||
|
||||
// transfer texture data
|
||||
|
||||
if ( texture.isDataTexture || texture.isDataArrayTexture || texture.isData3DTexture ) {
|
||||
|
||||
this._copyBufferToTexture( options.image, textureData.texture, textureDescriptorGPU, 0, false );
|
||||
|
||||
} else if ( texture.isCompressedTexture ) {
|
||||
|
||||
this._copyCompressedBufferToTexture( texture.mipmaps, textureData.texture, textureDescriptorGPU );
|
||||
|
||||
} else if ( texture.isCubeTexture ) {
|
||||
|
||||
this._copyCubeMapToTexture( options.images, textureData.texture, textureDescriptorGPU, texture.flipY );
|
||||
|
||||
} else if ( texture.isVideoTexture ) {
|
||||
|
||||
const video = texture.source.data;
|
||||
|
||||
textureData.externalTexture = video;
|
||||
|
||||
} else {
|
||||
|
||||
this._copyImageToTexture( options.image, textureData.texture, textureDescriptorGPU, 0, texture.flipY );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
textureData.version = texture.version;
|
||||
|
||||
if ( texture.onUpdate ) texture.onUpdate( texture );
|
||||
|
||||
}
|
||||
|
||||
async copyTextureToBuffer( texture, x, y, width, height ) {
|
||||
|
||||
const device = this.backend.device;
|
||||
|
||||
const textureData = this.backend.get( texture );
|
||||
const textureGPU = textureData.texture;
|
||||
const format = textureData.textureDescriptorGPU.format;
|
||||
const bytesPerTexel = this._getBytesPerTexel( format );
|
||||
|
||||
const readBuffer = device.createBuffer(
|
||||
{
|
||||
size: width * height * bytesPerTexel,
|
||||
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
||||
}
|
||||
);
|
||||
|
||||
const encoder = device.createCommandEncoder();
|
||||
|
||||
encoder.copyTextureToBuffer(
|
||||
{
|
||||
texture: textureGPU,
|
||||
origin: { x, y },
|
||||
},
|
||||
{
|
||||
buffer: readBuffer,
|
||||
bytesPerRow: width * bytesPerTexel
|
||||
},
|
||||
{
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
const typedArrayType = this._getTypedArrayType( format );
|
||||
|
||||
device.queue.submit( [ encoder.finish() ] );
|
||||
|
||||
await readBuffer.mapAsync( GPUMapMode.READ );
|
||||
|
||||
const buffer = readBuffer.getMappedRange();
|
||||
|
||||
return new typedArrayType( buffer );
|
||||
|
||||
}
|
||||
|
||||
_isEnvironmentTexture( texture ) {
|
||||
|
||||
const mapping = texture.mapping;
|
||||
|
||||
return ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) || ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
|
||||
|
||||
}
|
||||
|
||||
_getDefaultTextureGPU() {
|
||||
|
||||
let defaultTexture = this.defaultTexture;
|
||||
|
||||
if ( defaultTexture === null ) {
|
||||
|
||||
const texture = new Texture();
|
||||
texture.minFilter = NearestFilter;
|
||||
texture.magFilter = NearestFilter;
|
||||
|
||||
this.createTexture( texture, { width: 1, height: 1 } );
|
||||
|
||||
this.defaultTexture = defaultTexture = texture;
|
||||
|
||||
}
|
||||
|
||||
return this.backend.get( defaultTexture ).texture;
|
||||
|
||||
}
|
||||
|
||||
_getDefaultCubeTextureGPU() {
|
||||
|
||||
let defaultCubeTexture = this.defaultTexture;
|
||||
|
||||
if ( defaultCubeTexture === null ) {
|
||||
|
||||
const texture = new CubeTexture();
|
||||
texture.minFilter = NearestFilter;
|
||||
texture.magFilter = NearestFilter;
|
||||
|
||||
this.createTexture( texture, { width: 1, height: 1, depth: 6 } );
|
||||
|
||||
this.defaultCubeTexture = defaultCubeTexture = texture;
|
||||
|
||||
}
|
||||
|
||||
return this.backend.get( defaultCubeTexture ).texture;
|
||||
|
||||
}
|
||||
|
||||
_copyCubeMapToTexture( images, textureGPU, textureDescriptorGPU, flipY ) {
|
||||
|
||||
for ( let i = 0; i < 6; i ++ ) {
|
||||
|
||||
const image = images[ i ];
|
||||
|
||||
const flipIndex = flipY === true ? _flipMap[ i ] : i;
|
||||
|
||||
if ( image.isDataTexture ) {
|
||||
|
||||
this._copyBufferToTexture( image.image, textureGPU, textureDescriptorGPU, flipIndex, flipY );
|
||||
|
||||
} else {
|
||||
|
||||
this._copyImageToTexture( image, textureGPU, textureDescriptorGPU, flipIndex, flipY );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_copyImageToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY ) {
|
||||
|
||||
const device = this.backend.device;
|
||||
|
||||
device.queue.copyExternalImageToTexture(
|
||||
{
|
||||
source: image
|
||||
}, {
|
||||
texture: textureGPU,
|
||||
mipLevel: 0,
|
||||
origin: { x: 0, y: 0, z: originDepth }
|
||||
}, {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
depthOrArrayLayers: 1
|
||||
}
|
||||
);
|
||||
|
||||
if ( flipY === true ) {
|
||||
|
||||
this._flipY( textureGPU, textureDescriptorGPU, originDepth );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_getPassUtils() {
|
||||
|
||||
let passUtils = this._passUtils;
|
||||
|
||||
if ( passUtils === null ) {
|
||||
|
||||
this._passUtils = passUtils = new WebGPUTexturePassUtils( this.backend.device );
|
||||
|
||||
}
|
||||
|
||||
return passUtils;
|
||||
|
||||
}
|
||||
|
||||
_generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer = 0 ) {
|
||||
|
||||
this._getPassUtils().generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer );
|
||||
|
||||
}
|
||||
|
||||
_flipY( textureGPU, textureDescriptorGPU, originDepth = 0 ) {
|
||||
|
||||
this._getPassUtils().flipY( textureGPU, textureDescriptorGPU, originDepth );
|
||||
|
||||
}
|
||||
|
||||
_copyBufferToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY ) {
|
||||
|
||||
// @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
|
||||
// @TODO: Consider to support valid buffer layouts with other formats like RGB
|
||||
|
||||
const device = this.backend.device;
|
||||
|
||||
const data = image.data;
|
||||
|
||||
const bytesPerTexel = this._getBytesPerTexel( textureDescriptorGPU.format );
|
||||
const bytesPerRow = image.width * bytesPerTexel;
|
||||
|
||||
device.queue.writeTexture(
|
||||
{
|
||||
texture: textureGPU,
|
||||
mipLevel: 0,
|
||||
origin: { x: 0, y: 0, z: originDepth }
|
||||
},
|
||||
data,
|
||||
{
|
||||
offset: 0,
|
||||
bytesPerRow
|
||||
},
|
||||
{
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
depthOrArrayLayers: ( image.depth !== undefined ) ? image.depth : 1
|
||||
} );
|
||||
|
||||
if ( flipY === true ) {
|
||||
|
||||
this._flipY( textureGPU, textureDescriptorGPU, originDepth );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) {
|
||||
|
||||
// @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
|
||||
|
||||
const device = this.backend.device;
|
||||
|
||||
const blockData = this._getBlockData( textureDescriptorGPU.format );
|
||||
|
||||
for ( let i = 0; i < mipmaps.length; i ++ ) {
|
||||
|
||||
const mipmap = mipmaps[ i ];
|
||||
|
||||
const width = mipmap.width;
|
||||
const height = mipmap.height;
|
||||
|
||||
const bytesPerRow = Math.ceil( width / blockData.width ) * blockData.byteLength;
|
||||
|
||||
device.queue.writeTexture(
|
||||
{
|
||||
texture: textureGPU,
|
||||
mipLevel: i
|
||||
},
|
||||
mipmap.data,
|
||||
{
|
||||
offset: 0,
|
||||
bytesPerRow
|
||||
},
|
||||
{
|
||||
width: Math.ceil( width / blockData.width ) * blockData.width,
|
||||
height: Math.ceil( height / blockData.width ) * blockData.width,
|
||||
depthOrArrayLayers: 1
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_getBlockData( format ) {
|
||||
|
||||
// this method is only relevant for compressed texture formats
|
||||
|
||||
if ( format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; // DXT1
|
||||
if ( format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT3
|
||||
if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5
|
||||
if ( format === GPUTextureFormat.BC4RUnorm || format === GPUTextureFormat.BC4RSNorm ) return { byteLength: 8, width: 4, height: 4 }; // RGTC1
|
||||
if ( format === GPUTextureFormat.BC5RGUnorm || format === GPUTextureFormat.BC5RGSnorm ) return { byteLength: 16, width: 4, height: 4 }; // RGTC2
|
||||
if ( format === GPUTextureFormat.BC6HRGBUFloat || format === GPUTextureFormat.BC6HRGBFloat ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (float)
|
||||
if ( format === GPUTextureFormat.BC7RGBAUnorm || format === GPUTextureFormat.BC7RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (unorm)
|
||||
|
||||
if ( format === GPUTextureFormat.ETC2RGB8Unorm || format === GPUTextureFormat.ETC2RGB8UnormSRGB ) return { byteLength: 8, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.ETC2RGB8A1Unorm || format === GPUTextureFormat.ETC2RGB8A1UnormSRGB ) return { byteLength: 8, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.ETC2RGBA8Unorm || format === GPUTextureFormat.ETC2RGBA8UnormSRGB ) return { byteLength: 16, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.EACR11Unorm ) return { byteLength: 8, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.EACR11Snorm ) return { byteLength: 8, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.EACRG11Unorm ) return { byteLength: 16, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.EACRG11Snorm ) return { byteLength: 16, width: 4, height: 4 };
|
||||
|
||||
if ( format === GPUTextureFormat.ASTC4x4Unorm || format === GPUTextureFormat.ASTC4x4UnormSRGB ) return { byteLength: 16, width: 4, height: 4 };
|
||||
if ( format === GPUTextureFormat.ASTC5x4Unorm || format === GPUTextureFormat.ASTC5x4UnormSRGB ) return { byteLength: 16, width: 5, height: 4 };
|
||||
if ( format === GPUTextureFormat.ASTC5x5Unorm || format === GPUTextureFormat.ASTC5x5UnormSRGB ) return { byteLength: 16, width: 5, height: 5 };
|
||||
if ( format === GPUTextureFormat.ASTC6x5Unorm || format === GPUTextureFormat.ASTC6x5UnormSRGB ) return { byteLength: 16, width: 6, height: 5 };
|
||||
if ( format === GPUTextureFormat.ASTC6x6Unorm || format === GPUTextureFormat.ASTC6x6UnormSRGB ) return { byteLength: 16, width: 6, height: 6 };
|
||||
if ( format === GPUTextureFormat.ASTC8x5Unorm || format === GPUTextureFormat.ASTC8x5UnormSRGB ) return { byteLength: 16, width: 8, height: 5 };
|
||||
if ( format === GPUTextureFormat.ASTC8x6Unorm || format === GPUTextureFormat.ASTC8x6UnormSRGB ) return { byteLength: 16, width: 8, height: 6 };
|
||||
if ( format === GPUTextureFormat.ASTC8x8Unorm || format === GPUTextureFormat.ASTC8x8UnormSRGB ) return { byteLength: 16, width: 8, height: 8 };
|
||||
if ( format === GPUTextureFormat.ASTC10x5Unorm || format === GPUTextureFormat.ASTC10x5UnormSRGB ) return { byteLength: 16, width: 10, height: 5 };
|
||||
if ( format === GPUTextureFormat.ASTC10x6Unorm || format === GPUTextureFormat.ASTC10x6UnormSRGB ) return { byteLength: 16, width: 10, height: 6 };
|
||||
if ( format === GPUTextureFormat.ASTC10x8Unorm || format === GPUTextureFormat.ASTC10x8UnormSRGB ) return { byteLength: 16, width: 10, height: 8 };
|
||||
if ( format === GPUTextureFormat.ASTC10x10Unorm || format === GPUTextureFormat.ASTC10x10UnormSRGB ) return { byteLength: 16, width: 10, height: 10 };
|
||||
if ( format === GPUTextureFormat.ASTC12x10Unorm || format === GPUTextureFormat.ASTC12x10UnormSRGB ) return { byteLength: 16, width: 12, height: 10 };
|
||||
if ( format === GPUTextureFormat.ASTC12x12Unorm || format === GPUTextureFormat.ASTC12x12UnormSRGB ) return { byteLength: 16, width: 12, height: 12 };
|
||||
|
||||
}
|
||||
|
||||
_convertAddressMode( value ) {
|
||||
|
||||
let addressMode = GPUAddressMode.ClampToEdge;
|
||||
|
||||
if ( value === RepeatWrapping ) {
|
||||
|
||||
addressMode = GPUAddressMode.Repeat;
|
||||
|
||||
} else if ( value === MirroredRepeatWrapping ) {
|
||||
|
||||
addressMode = GPUAddressMode.MirrorRepeat;
|
||||
|
||||
}
|
||||
|
||||
return addressMode;
|
||||
|
||||
}
|
||||
|
||||
_convertFilterMode( value ) {
|
||||
|
||||
let filterMode = GPUFilterMode.Linear;
|
||||
|
||||
if ( value === NearestFilter || value === NearestMipmapNearestFilter || value === NearestMipmapLinearFilter ) {
|
||||
|
||||
filterMode = GPUFilterMode.Nearest;
|
||||
|
||||
}
|
||||
|
||||
return filterMode;
|
||||
|
||||
}
|
||||
|
||||
_getBytesPerTexel( format ) {
|
||||
|
||||
if ( format === GPUTextureFormat.R8Unorm ) return 1;
|
||||
if ( format === GPUTextureFormat.R16Float ) return 2;
|
||||
if ( format === GPUTextureFormat.RG8Unorm ) return 2;
|
||||
if ( format === GPUTextureFormat.RG16Float ) return 4;
|
||||
if ( format === GPUTextureFormat.R32Float ) return 4;
|
||||
if ( format === GPUTextureFormat.RGBA8Unorm || format === GPUTextureFormat.RGBA8UnormSRGB ) return 4;
|
||||
if ( format === GPUTextureFormat.RG32Float ) return 8;
|
||||
if ( format === GPUTextureFormat.RGBA16Float ) return 8;
|
||||
if ( format === GPUTextureFormat.RGBA32Float ) return 16;
|
||||
|
||||
}
|
||||
|
||||
_getTypedArrayType( format ) {
|
||||
|
||||
if ( format === GPUTextureFormat.R8Uint ) return Uint8Array;
|
||||
if ( format === GPUTextureFormat.R8Sint ) return Int8Array;
|
||||
if ( format === GPUTextureFormat.R8Unorm ) return Uint8Array;
|
||||
if ( format === GPUTextureFormat.R8Snorm ) return Int8Array;
|
||||
if ( format === GPUTextureFormat.RG8Uint ) return Uint8Array;
|
||||
if ( format === GPUTextureFormat.RG8Sint ) return Int8Array;
|
||||
if ( format === GPUTextureFormat.RG8Unorm ) return Uint8Array;
|
||||
if ( format === GPUTextureFormat.RG8Snorm ) return Int8Array;
|
||||
if ( format === GPUTextureFormat.RGBA8Uint ) return Uint8Array;
|
||||
if ( format === GPUTextureFormat.RGBA8Sint ) return Int8Array;
|
||||
if ( format === GPUTextureFormat.RGBA8Unorm ) return Uint8Array;
|
||||
if ( format === GPUTextureFormat.RGBA8Snorm ) return Int8Array;
|
||||
|
||||
|
||||
if ( format === GPUTextureFormat.R16Uint ) return Uint16Array;
|
||||
if ( format === GPUTextureFormat.R16Sint ) return Int16Array;
|
||||
if ( format === GPUTextureFormat.RG16Uint ) return Uint16Array;
|
||||
if ( format === GPUTextureFormat.RG16Sint ) return Int16Array;
|
||||
if ( format === GPUTextureFormat.RGBA16Uint ) return Uint16Array;
|
||||
if ( format === GPUTextureFormat.RGBA16Sint ) return Int16Array;
|
||||
|
||||
|
||||
if ( format === GPUTextureFormat.R32Uint ) return Uint32Array;
|
||||
if ( format === GPUTextureFormat.R32Sint ) return Int32Array;
|
||||
if ( format === GPUTextureFormat.R32Float ) return Float32Array;
|
||||
if ( format === GPUTextureFormat.RG32Uint ) return Uint32Array;
|
||||
if ( format === GPUTextureFormat.RG32Sint ) return Int32Array;
|
||||
if ( format === GPUTextureFormat.RG32Float ) return Float32Array;
|
||||
if ( format === GPUTextureFormat.RGBA32Uint ) return Uint32Array;
|
||||
if ( format === GPUTextureFormat.RGBA32Sint ) return Int32Array;
|
||||
if ( format === GPUTextureFormat.RGBA32Float ) return Float32Array;
|
||||
|
||||
}
|
||||
|
||||
_getDimension( texture ) {
|
||||
|
||||
let dimension;
|
||||
|
||||
if ( texture.isData3DTexture ) {
|
||||
|
||||
dimension = GPUTextureDimension.ThreeD;
|
||||
|
||||
} else {
|
||||
|
||||
dimension = GPUTextureDimension.TwoD;
|
||||
|
||||
}
|
||||
|
||||
return dimension;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function getFormat( texture, device = null ) {
|
||||
|
||||
const format = texture.format;
|
||||
const type = texture.type;
|
||||
const colorSpace = texture.colorSpace;
|
||||
|
||||
let formatGPU;
|
||||
|
||||
if ( /*texture.isRenderTargetTexture === true ||*/ texture.isFramebufferTexture === true ) {
|
||||
|
||||
formatGPU = GPUTextureFormat.BGRA8Unorm;
|
||||
|
||||
} else if ( texture.isCompressedTexture === true ) {
|
||||
|
||||
switch ( format ) {
|
||||
|
||||
case RGBA_S3TC_DXT1_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC1RGBAUnormSRGB : GPUTextureFormat.BC1RGBAUnorm;
|
||||
break;
|
||||
|
||||
case RGBA_S3TC_DXT3_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC2RGBAUnormSRGB : GPUTextureFormat.BC2RGBAUnorm;
|
||||
break;
|
||||
|
||||
case RGBA_S3TC_DXT5_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC3RGBAUnormSRGB : GPUTextureFormat.BC3RGBAUnorm;
|
||||
break;
|
||||
|
||||
case RGB_ETC2_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGB8UnormSRGB : GPUTextureFormat.ETC2RGB8Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ETC2_EAC_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGBA8UnormSRGB : GPUTextureFormat.ETC2RGBA8Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_4x4_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC4x4UnormSRGB : GPUTextureFormat.ASTC4x4Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_5x4_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x4UnormSRGB : GPUTextureFormat.ASTC5x4Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_5x5_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x5UnormSRGB : GPUTextureFormat.ASTC5x5Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_6x5_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x5UnormSRGB : GPUTextureFormat.ASTC6x5Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_6x6_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x6UnormSRGB : GPUTextureFormat.ASTC6x6Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_8x5_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x5UnormSRGB : GPUTextureFormat.ASTC8x5Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_8x6_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x6UnormSRGB : GPUTextureFormat.ASTC8x6Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_8x8_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x8UnormSRGB : GPUTextureFormat.ASTC8x8Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_10x5_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x5UnormSRGB : GPUTextureFormat.ASTC10x5Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_10x6_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x6UnormSRGB : GPUTextureFormat.ASTC10x6Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_10x8_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x8UnormSRGB : GPUTextureFormat.ASTC10x8Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_10x10_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x10UnormSRGB : GPUTextureFormat.ASTC10x10Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_12x10_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x10UnormSRGB : GPUTextureFormat.ASTC12x10Unorm;
|
||||
break;
|
||||
|
||||
case RGBA_ASTC_12x12_Format:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture format.', format );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
switch ( format ) {
|
||||
|
||||
case RGBAFormat:
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case UnsignedByteType:
|
||||
formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm;
|
||||
break;
|
||||
|
||||
case HalfFloatType:
|
||||
formatGPU = GPUTextureFormat.RGBA16Float;
|
||||
break;
|
||||
|
||||
case FloatType:
|
||||
formatGPU = GPUTextureFormat.RGBA32Float;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture type with RGBAFormat.', type );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RedFormat:
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case UnsignedByteType:
|
||||
formatGPU = GPUTextureFormat.R8Unorm;
|
||||
break;
|
||||
|
||||
case HalfFloatType:
|
||||
formatGPU = GPUTextureFormat.R16Float;
|
||||
break;
|
||||
|
||||
case FloatType:
|
||||
formatGPU = GPUTextureFormat.R32Float;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture type with RedFormat.', type );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RGFormat:
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case UnsignedByteType:
|
||||
formatGPU = GPUTextureFormat.RG8Unorm;
|
||||
break;
|
||||
|
||||
case HalfFloatType:
|
||||
formatGPU = GPUTextureFormat.RG16Float;
|
||||
break;
|
||||
|
||||
case FloatType:
|
||||
formatGPU = GPUTextureFormat.RG32Float;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture type with RGFormat.', type );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DepthFormat:
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case UnsignedShortType:
|
||||
formatGPU = GPUTextureFormat.Depth16Unorm;
|
||||
break;
|
||||
|
||||
case UnsignedIntType:
|
||||
formatGPU = GPUTextureFormat.Depth24Plus;
|
||||
break;
|
||||
|
||||
case FloatType:
|
||||
formatGPU = GPUTextureFormat.Depth32Float;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture type with DepthFormat.', type );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DepthStencilFormat:
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case UnsignedInt248Type:
|
||||
formatGPU = GPUTextureFormat.Depth24PlusStencil8;
|
||||
break;
|
||||
|
||||
case FloatType:
|
||||
|
||||
if ( device && device.features.has( GPUFeatureName.Depth32FloatStencil8 ) === false ) {
|
||||
|
||||
console.error( 'WebGPURenderer: Depth textures with DepthStencilFormat + FloatType can only be used with the "depth32float-stencil8" GPU feature.' );
|
||||
|
||||
}
|
||||
|
||||
formatGPU = GPUTextureFormat.Depth32FloatStencil8;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture type with DepthStencilFormat.', type );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( 'WebGPURenderer: Unsupported texture format.', format );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return formatGPU;
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUTextureUtils;
|
||||
93
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js
generated
vendored
Normal file
93
node_modules/three/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import { GPUPrimitiveTopology, GPUTextureFormat } from './WebGPUConstants.js';
|
||||
|
||||
class WebGPUUtils {
|
||||
|
||||
constructor( backend ) {
|
||||
|
||||
this.backend = backend;
|
||||
|
||||
}
|
||||
|
||||
getCurrentDepthStencilFormat( renderContext ) {
|
||||
|
||||
let format;
|
||||
|
||||
if ( renderContext.depthTexture !== null ) {
|
||||
|
||||
format = this.getTextureFormatGPU( renderContext.depthTexture );
|
||||
|
||||
} else if ( renderContext.depth && renderContext.stencil ) {
|
||||
|
||||
format = GPUTextureFormat.Depth24PlusStencil8;
|
||||
|
||||
} else if ( renderContext.depth ) {
|
||||
|
||||
format = GPUTextureFormat.Depth24Plus;
|
||||
|
||||
}
|
||||
|
||||
return format;
|
||||
|
||||
}
|
||||
|
||||
getTextureFormatGPU( texture ) {
|
||||
|
||||
return this.backend.get( texture ).texture.format;
|
||||
|
||||
}
|
||||
|
||||
getCurrentColorFormat( renderContext ) {
|
||||
|
||||
let format;
|
||||
|
||||
if ( renderContext.textures !== null ) {
|
||||
|
||||
format = this.getTextureFormatGPU( renderContext.textures[ 0 ] );
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
format = GPUTextureFormat.BGRA8Unorm; // default context format
|
||||
|
||||
}
|
||||
|
||||
return format;
|
||||
|
||||
}
|
||||
|
||||
getCurrentColorSpace( renderContext ) {
|
||||
|
||||
if ( renderContext.textures !== null ) {
|
||||
|
||||
return renderContext.textures[ 0 ].colorSpace;
|
||||
|
||||
}
|
||||
|
||||
return this.backend.renderer.outputColorSpace;
|
||||
|
||||
}
|
||||
|
||||
getPrimitiveTopology( object, material ) {
|
||||
|
||||
if ( object.isPoints ) return GPUPrimitiveTopology.PointList;
|
||||
else if ( object.isLineSegments || ( object.isMesh && material.wireframe === true ) ) return GPUPrimitiveTopology.LineList;
|
||||
else if ( object.isLine ) return GPUPrimitiveTopology.LineStrip;
|
||||
else if ( object.isMesh ) return GPUPrimitiveTopology.TriangleList;
|
||||
|
||||
}
|
||||
|
||||
getSampleCount( renderContext ) {
|
||||
|
||||
if ( renderContext.textures !== null ) {
|
||||
|
||||
return renderContext.sampleCount;
|
||||
|
||||
}
|
||||
|
||||
return this.backend.parameters.sampleCount;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WebGPUUtils;
|
||||
Reference in New Issue
Block a user