Skip to content

Commit

Permalink
WebGPU: Fix collisions in bind group cache (#15722)
Browse files Browse the repository at this point in the history
* Fix anisotropy value used in the sampler hash code calculation

* Fix collisions in the bind group cache
  • Loading branch information
Popov72 authored Oct 21, 2024
1 parent 730b46b commit 9e61762
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
17 changes: 15 additions & 2 deletions packages/dev/core/src/Engines/WebGPU/webgpuCacheBindGroups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ import type { InternalTexture } from "../../Materials/Textures/internalTexture";
import type { ExternalTexture } from "../../Materials/Textures/externalTexture";
import type { WebGPUDrawContext } from "./webgpuDrawContext";

/**
* Sampler hash codes are 19 bits long, so using a start value of 2^20 for buffer ids will ensure we can't have any collision with the sampler hash codes
*/
const bufferIdStart = 1 << 20;

/**
* textureIdStart is added to texture ids to ensure we can't have any collision with the buffer ids / sampler hash codes.
* 2^35 for textureIdStart means we can have:
* - 2^(35-20) = 2^15 = 32768 possible buffer ids
* - 2^(53-35) = 2^18 = 524288 possible texture ids
*/
const textureIdStart = 2 ** 35;

class WebGPUBindGroupCacheNode {
public values: { [id: number]: WebGPUBindGroupCacheNode };
public bindGroups: GPUBindGroup[];
Expand Down Expand Up @@ -94,7 +107,7 @@ export class WebGPUCacheBindGroups {
}

for (const bufferName of webgpuPipelineContext.shaderProcessingContext.bufferNames) {
const uboId = drawContext.buffers[bufferName]?.uniqueId ?? 0;
const uboId = (drawContext.buffers[bufferName]?.uniqueId ?? 0) + bufferIdStart;
let nextNode = node.values[uboId];
if (!nextNode) {
nextNode = new WebGPUBindGroupCacheNode();
Expand All @@ -114,7 +127,7 @@ export class WebGPUCacheBindGroups {
}

for (const textureName of webgpuPipelineContext.shaderProcessingContext.textureNames) {
const textureId = materialContext.textures[textureName]?.texture?.uniqueId ?? 0;
const textureId = (materialContext.textures[textureName]?.texture?.uniqueId ?? 0) + textureIdStart;
let nextNode = node.values[textureId];
if (!nextNode) {
nextNode = new WebGPUBindGroupCacheNode();
Expand Down
5 changes: 2 additions & 3 deletions packages/dev/core/src/Engines/WebGPU/webgpuCacheSampler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class WebGPUCacheSampler {

public static GetSamplerHashCode(sampler: TextureSampler): number {
// The WebGPU spec currently only allows values 1 and 4 for anisotropy
const anisotropy = sampler._cachedAnisotropicFilteringLevel && sampler._cachedAnisotropicFilteringLevel > 1 ? 4 : 1;
const anisotropy = sampler._cachedAnisotropicFilteringLevel ? sampler._cachedAnisotropicFilteringLevel : 1;
const code =
filterToBits[sampler.samplingMode] +
comparisonFunctionToBits[(sampler._comparisonFunction || 0x0202) - 0x0200 + 1] +
Expand Down Expand Up @@ -243,8 +243,7 @@ export class WebGPUCacheSampler {
}

private static _GetSamplerDescriptor(sampler: TextureSampler, label?: string): GPUSamplerDescriptor {
// The WebGPU spec currently only allows values 1 and 4 for anisotropy
const anisotropy = sampler.useMipMaps && sampler._cachedAnisotropicFilteringLevel && sampler._cachedAnisotropicFilteringLevel > 1 ? 4 : 1;
const anisotropy = sampler.useMipMaps && sampler._cachedAnisotropicFilteringLevel ? sampler._cachedAnisotropicFilteringLevel : 1;
const filterDescriptor = this._GetSamplerFilterDescriptor(sampler, anisotropy);
return {
label,
Expand Down

0 comments on commit 9e61762

Please sign in to comment.