@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
280 lines (279 loc) • 13.3 kB
JavaScript
const filterToBits = [
0 | (0 << 1) | (0 << 2), // not used
0 | (0 << 1) | (0 << 2), // TEXTURE_NEAREST_SAMPLINGMODE / TEXTURE_NEAREST_NEAREST
1 | (1 << 1) | (0 << 2), // TEXTURE_BILINEAR_SAMPLINGMODE / TEXTURE_LINEAR_LINEAR
1 | (1 << 1) | (1 << 2), // TEXTURE_TRILINEAR_SAMPLINGMODE / TEXTURE_LINEAR_LINEAR_MIPLINEAR
0 | (0 << 1) | (0 << 2), // TEXTURE_NEAREST_NEAREST_MIPNEAREST
0 | (1 << 1) | (0 << 2), // TEXTURE_NEAREST_LINEAR_MIPNEAREST
0 | (1 << 1) | (1 << 2), // TEXTURE_NEAREST_LINEAR_MIPLINEAR
0 | (1 << 1) | (0 << 2), // TEXTURE_NEAREST_LINEAR
0 | (0 << 1) | (1 << 2), // TEXTURE_NEAREST_NEAREST_MIPLINEAR
1 | (0 << 1) | (0 << 2), // TEXTURE_LINEAR_NEAREST_MIPNEAREST
1 | (0 << 1) | (1 << 2), // TEXTURE_LINEAR_NEAREST_MIPLINEAR
1 | (1 << 1) | (0 << 2), // TEXTURE_LINEAR_LINEAR_MIPNEAREST
1 | (0 << 1) | (0 << 2), // TEXTURE_LINEAR_NEAREST
];
// subtract 0x01FF from the comparison function value before indexing this array!
const comparisonFunctionToBits = [
(0 << 3) | (0 << 4) | (0 << 5) | (0 << 6), // undefined
(0 << 3) | (0 << 4) | (0 << 5) | (1 << 6), // NEVER
(0 << 3) | (0 << 4) | (1 << 5) | (0 << 6), // LESS
(0 << 3) | (0 << 4) | (1 << 5) | (1 << 6), // EQUAL
(0 << 3) | (1 << 4) | (0 << 5) | (0 << 6), // LEQUAL
(0 << 3) | (1 << 4) | (0 << 5) | (1 << 6), // GREATER
(0 << 3) | (1 << 4) | (1 << 5) | (0 << 6), // NOTEQUAL
(0 << 3) | (1 << 4) | (1 << 5) | (1 << 6), // GEQUAL
(1 << 3) | (0 << 4) | (0 << 5) | (0 << 6), // ALWAYS
];
const filterNoMipToBits = [
0 << 7, // not used
1 << 7, // TEXTURE_NEAREST_SAMPLINGMODE / TEXTURE_NEAREST_NEAREST
1 << 7, // TEXTURE_BILINEAR_SAMPLINGMODE / TEXTURE_LINEAR_LINEAR
0 << 7, // TEXTURE_TRILINEAR_SAMPLINGMODE / TEXTURE_LINEAR_LINEAR_MIPLINEAR
0 << 7, // TEXTURE_NEAREST_NEAREST_MIPNEAREST
0 << 7, // TEXTURE_NEAREST_LINEAR_MIPNEAREST
0 << 7, // TEXTURE_NEAREST_LINEAR_MIPLINEAR
1 << 7, // TEXTURE_NEAREST_LINEAR
0 << 7, // TEXTURE_NEAREST_NEAREST_MIPLINEAR
0 << 7, // TEXTURE_LINEAR_NEAREST_MIPNEAREST
0 << 7, // TEXTURE_LINEAR_NEAREST_MIPLINEAR
0 << 7, // TEXTURE_LINEAR_LINEAR_MIPNEAREST
1 << 7, // TEXTURE_LINEAR_NEAREST
];
/** @internal */
export class WebGPUCacheSampler {
constructor(device) {
this._samplers = {};
this._device = device;
this.disabled = false;
}
static GetSamplerHashCode(sampler) {
// The WebGPU spec currently only allows values 1 and 4 for anisotropy
const anisotropy = sampler._cachedAnisotropicFilteringLevel ? sampler._cachedAnisotropicFilteringLevel : 1;
const code = filterToBits[sampler.samplingMode] +
comparisonFunctionToBits[(sampler._comparisonFunction || 0x0202) - 0x0200 + 1] +
filterNoMipToBits[sampler.samplingMode] + // handle the lodMinClamp = lodMaxClamp = 0 case when no filter used for mip mapping
((sampler._cachedWrapU ?? 1) << 8) +
((sampler._cachedWrapV ?? 1) << 10) +
((sampler._cachedWrapR ?? 1) << 12) +
((sampler.useMipMaps ? 1 : 0) << 14) + // need to factor this in because _getSamplerFilterDescriptor depends on samplingMode AND useMipMaps!
(anisotropy << 15);
return code;
}
static _GetSamplerFilterDescriptor(sampler, anisotropy) {
let magFilter, minFilter, mipmapFilter, lodMinClamp, lodMaxClamp;
const useMipMaps = sampler.useMipMaps;
switch (sampler.samplingMode) {
case 11:
magFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
minFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
if (!useMipMaps) {
lodMinClamp = lodMaxClamp = 0;
}
break;
case 3:
case 3:
magFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
minFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
if (!useMipMaps) {
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
}
else {
mipmapFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
}
break;
case 8:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
if (!useMipMaps) {
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
}
else {
mipmapFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
}
break;
case 4:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
if (!useMipMaps) {
lodMinClamp = lodMaxClamp = 0;
}
break;
case 5:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
if (!useMipMaps) {
lodMinClamp = lodMaxClamp = 0;
}
break;
case 6:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
if (!useMipMaps) {
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
}
else {
mipmapFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
}
break;
case 7:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
break;
case 1:
case 1:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
break;
case 9:
magFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
if (!useMipMaps) {
lodMinClamp = lodMaxClamp = 0;
}
break;
case 10:
magFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
if (!useMipMaps) {
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
}
else {
mipmapFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
}
break;
case 2:
case 2:
magFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
minFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
// In WebGL, if sampling mode is TEXTURE_BILINEAR_SAMPLINGMODE and anisotropy is greater than 1, anisotropy is enabled for the sampler
if (anisotropy > 1) {
mipmapFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
}
else {
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
}
break;
case 12:
magFilter = "linear" /* WebGPUConstants.FilterMode.Linear */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
break;
default:
magFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
minFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
mipmapFilter = "nearest" /* WebGPUConstants.FilterMode.Nearest */;
lodMinClamp = lodMaxClamp = 0;
break;
}
if (anisotropy > 1 && (lodMinClamp !== 0 || lodMaxClamp !== 0)) {
return {
magFilter: "linear" /* WebGPUConstants.FilterMode.Linear */,
minFilter: "linear" /* WebGPUConstants.FilterMode.Linear */,
mipmapFilter: "linear" /* WebGPUConstants.FilterMode.Linear */,
anisotropyEnabled: true,
};
}
return {
magFilter,
minFilter,
mipmapFilter,
lodMinClamp,
lodMaxClamp,
};
}
static _GetWrappingMode(mode) {
switch (mode) {
case 1:
return "repeat" /* WebGPUConstants.AddressMode.Repeat */;
case 0:
return "clamp-to-edge" /* WebGPUConstants.AddressMode.ClampToEdge */;
case 2:
return "mirror-repeat" /* WebGPUConstants.AddressMode.MirrorRepeat */;
}
return "repeat" /* WebGPUConstants.AddressMode.Repeat */;
}
static _GetSamplerWrappingDescriptor(sampler) {
return {
addressModeU: this._GetWrappingMode(sampler._cachedWrapU),
addressModeV: this._GetWrappingMode(sampler._cachedWrapV),
addressModeW: this._GetWrappingMode(sampler._cachedWrapR),
};
}
static _GetSamplerDescriptor(sampler, label) {
// The check with 2 is to be iso with the WebGL implementation
let anisotropy = (sampler.useMipMaps || sampler.samplingMode === 2) && sampler._cachedAnisotropicFilteringLevel
? sampler._cachedAnisotropicFilteringLevel
: 1;
// To be iso with the WebGL implementation
if (sampler.samplingMode !== 11 &&
sampler.samplingMode !== 3 &&
sampler.samplingMode !== 2) {
anisotropy = 1;
}
const filterDescriptor = this._GetSamplerFilterDescriptor(sampler, anisotropy);
return {
label,
...filterDescriptor,
...this._GetSamplerWrappingDescriptor(sampler),
compare: sampler._comparisonFunction ? WebGPUCacheSampler.GetCompareFunction(sampler._comparisonFunction) : undefined,
maxAnisotropy: filterDescriptor.anisotropyEnabled ? anisotropy : 1,
};
}
static GetCompareFunction(compareFunction) {
switch (compareFunction) {
case 519:
return "always" /* WebGPUConstants.CompareFunction.Always */;
case 514:
return "equal" /* WebGPUConstants.CompareFunction.Equal */;
case 516:
return "greater" /* WebGPUConstants.CompareFunction.Greater */;
case 518:
return "greater-equal" /* WebGPUConstants.CompareFunction.GreaterEqual */;
case 513:
return "less" /* WebGPUConstants.CompareFunction.Less */;
case 515:
return "less-equal" /* WebGPUConstants.CompareFunction.LessEqual */;
case 512:
return "never" /* WebGPUConstants.CompareFunction.Never */;
case 517:
return "not-equal" /* WebGPUConstants.CompareFunction.NotEqual */;
default:
return "less" /* WebGPUConstants.CompareFunction.Less */;
}
}
getSampler(sampler, bypassCache = false, hash = 0, label) {
if (this.disabled) {
return this._device.createSampler(WebGPUCacheSampler._GetSamplerDescriptor(sampler, label));
}
if (bypassCache) {
hash = 0;
}
else if (hash === 0) {
hash = WebGPUCacheSampler.GetSamplerHashCode(sampler);
}
let gpuSampler = bypassCache ? undefined : this._samplers[hash];
if (!gpuSampler) {
gpuSampler = this._device.createSampler(WebGPUCacheSampler._GetSamplerDescriptor(sampler, label));
if (!bypassCache) {
this._samplers[hash] = gpuSampler;
}
}
return gpuSampler;
}
}
//# sourceMappingURL=webgpuCacheSampler.js.map