Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed binding group layout validation error (#207) #210

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/api/utils/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function bindingsDescriptorEquals(
b.storageBufferBindings = b.storageBufferBindings || [];
b.storageTextureBindings = b.storageTextureBindings || [];

if (a.pipeline !== b.pipeline) return false;
if (a.samplerBindings.length !== b.samplerBindings.length) return false;
if (!arrayEqual(a.samplerBindings, b.samplerBindings, samplerBindingEquals))
return false;
Expand Down
7 changes: 7 additions & 0 deletions src/webgpu/Device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import {
} from './utils';
import { preprocessShader_GLSL } from '../shader';
import { RenderBundle_WebGPU } from './RenderBundle';
import { MipmapGenerator } from './MipmapGenerator';

export class Device_WebGPU implements SwapChain, IDevice_WebGPU {
private swapChainWidth = 0;
Expand Down Expand Up @@ -123,6 +124,7 @@ export class Device_WebGPU implements SwapChain, IDevice_WebGPU {
private canvasContext: GPUCanvasContext;
private glsl_compile: typeof glsl_compile_;
private WGSLComposer: WGSLComposer;
private mipmapGenerator: MipmapGenerator;

constructor(
adapter: GPUAdapter,
Expand All @@ -137,6 +139,7 @@ export class Device_WebGPU implements SwapChain, IDevice_WebGPU {
this.canvasContext = canvasContext;
this.glsl_compile = glsl_compile;
this.WGSLComposer = wGSLComposer;
this.mipmapGenerator = new MipmapGenerator(device);

this.fallbackTexture2D = this.createFallbackTexture(
TextureDimension.TEXTURE_2D,
Expand Down Expand Up @@ -266,6 +269,10 @@ export class Device_WebGPU implements SwapChain, IDevice_WebGPU {
return this;
}

getMipmapGenerator(): MipmapGenerator {
return this.mipmapGenerator;
}

getCanvas(): HTMLCanvasElement | OffscreenCanvas {
return this.canvas;
}
Expand Down
127 changes: 127 additions & 0 deletions src/webgpu/MipmapGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
export class MipmapGenerator {
private readonly _device: GPUDevice;
private readonly _mipmapShader: GPUShaderModule;
private readonly _mipmapSampler: GPUSampler;
private readonly _pipelines: Map<GPUTextureFormat, GPURenderPipeline>;

constructor(device: GPUDevice) {
this._device = device;

this._mipmapShader = this._device.createShaderModule({
label: 'MipmapGenerator',
code: `
struct VSOutput {
@builtin(position) position: vec4f,
@location(0) texcoord: vec2f,
};

@vertex fn vs(
@builtin(vertex_index) vertexIndex : u32
) -> VSOutput {
let pos = array(
// 1st triangle
vec2f( 0.0, 0.0), // center
vec2f( 1.0, 0.0), // right, center
vec2f( 0.0, 1.0), // center, top

// 2nd triangle
vec2f( 0.0, 1.0), // center, top
vec2f( 1.0, 0.0), // right, center
vec2f( 1.0, 1.0), // right, top
);

var vsOutput: VSOutput;
let xy = pos[vertexIndex];
vsOutput.position = vec4f(xy * 2.0 - 1.0, 0.0, 1.0);
vsOutput.texcoord = vec2f(xy.x, 1.0 - xy.y);
return vsOutput;
}

@group(0) @binding(0) var ourSampler: sampler;
@group(0) @binding(1) var ourTexture: texture_2d<f32>;

@fragment fn fs(fsInput: VSOutput) -> @location(0) vec4f {
return textureSample(ourTexture, ourSampler, fsInput.texcoord);
}
`,
});
this._mipmapSampler = this._device.createSampler({
minFilter: 'linear',
});
this._pipelines = new Map();
}

private _requestPipeline(format: GPUTextureFormat) {
let pipeline = this._pipelines.get(format);
if (!pipeline) {
pipeline = this._device.createRenderPipeline({
layout: 'auto',
vertex: {
module: this._mipmapShader,
entryPoint: 'vs',
},
fragment: {
module: this._mipmapShader,
entryPoint: 'fs',
targets: [{ format }],
},
});
this._pipelines.set(format, pipeline);
}
return pipeline;
}

generateMipmap(texture: GPUTexture) {
const commandEncoder = this._device.createCommandEncoder({
label: 'mipmap generator command encoder',
});
const pipeline = this._requestPipeline(texture.format,);

let width = texture.width;
let height = texture.height;
let baseMipLevel = 0;

while ((width > 1 || height > 1) && baseMipLevel < texture.mipLevelCount - 1) {
width = Math.max(1, width / 2);
height = Math.max(1, height / 2);

const bindGroup = this._device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [
{
binding: 0,
resource: this._mipmapSampler,
},
{
binding: 1,
resource: texture.createView({
baseMipLevel,
mipLevelCount: 1,
}),
},
],
});

++baseMipLevel;

const pass = commandEncoder.beginRenderPass({
colorAttachments: [
{
view: texture.createView({
baseMipLevel,
mipLevelCount: 1,
}),
loadOp: 'clear',
storeOp: 'store',
},
],
});
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.draw(6);
pass.end();
}

this._device.queue.submit([commandEncoder.finish()]);
}
}
2 changes: 1 addition & 1 deletion src/webgpu/RenderPass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export class RenderPass_WebGPU implements RenderPass {
}

private flipY(y: number, h: number) {
const height = this.device['swapChainHeight'];
const height = this.gfxColorAttachment[0].height;
return height - y - h;
}

Expand Down
6 changes: 6 additions & 0 deletions src/webgpu/Texture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getBlockInformationFromFormat,
translateTextureViewDimension,
} from './utils';
import { Device_WebGPU } from './Device';

export class Texture_WebGPU
extends ResourceBase_WebGPU
Expand Down Expand Up @@ -86,6 +87,7 @@ export class Texture_WebGPU
GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.RENDER_ATTACHMENT,
mipLevelCount: this.mipLevelCount,
};
const texture = device.createTexture(textureDescriptor);

Expand All @@ -97,6 +99,10 @@ export class Texture_WebGPU
);
}

if(this.mipLevelCount > 1) {
(this.device as Device_WebGPU).getMipmapGenerator().generateMipmap(texture);
}

return [texture, width, height];
}

Expand Down
Loading