Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ describe('game of life example', () => {
textureStore(next, gid.xy, vec4u(u32(select(0i, 1i, nextAlive)), 0u, 0u, 0u));
}

requires readonly_and_readwrite_storage_textures;

struct fullScreenTriangle_Output {
@builtin(position) pos: vec4f,
@location(0) uv: vec2f,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ describe('jump flood (distance) example', () => {
);

expect(shaderCodes).toMatchInlineSnapshot(`
"@group(0) @binding(0) var<uniform> sizeUniform: vec3u;
"requires readonly_and_readwrite_storage_textures;

@group(0) @binding(0) var<uniform> sizeUniform: vec3u;

@group(1) @binding(1) var writeView: texture_storage_2d<rgba16float, write>;

Expand All @@ -47,6 +49,8 @@ describe('jump flood (distance) example', () => {
wrappedCallback(id.x, id.y, id.z);
}

requires readonly_and_readwrite_storage_textures;

@group(0) @binding(0) var<uniform> sizeUniform: vec3u;

@group(0) @binding(1) var<uniform> offsetUniform: i32;
Expand Down Expand Up @@ -258,6 +262,8 @@ describe('jump flood (distance) example', () => {
wrappedCallback(id.x, id.y, id.z);
}

requires readonly_and_readwrite_storage_textures;

@group(0) @binding(0) var<uniform> sizeUniform: vec3u;

@group(1) @binding(1) var readView: texture_storage_2d<rgba16float, read>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ describe('jump flood (voronoi) example', () => {
return textureSample(floodTexture, sampler_1, _arg_0.uv);
}

requires readonly_and_readwrite_storage_textures;

@group(0) @binding(0) var<uniform> sizeUniform: vec3u;

@group(0) @binding(1) var<uniform> offsetUniform: i32;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ describe('point light shadow example', () => {
);

expect(shaderCodes).toMatchInlineSnapshot(`
"var<immediate> viewProjectionMatrix: mat4x4f;
"requires immediate_address_space;

var<immediate> viewProjectionMatrix: mat4x4f;

struct vertexDepth_Output {
@builtin(position) pos: vec4f,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ describe('slime mold 3d example', () => {
textureStore(newState, gid.xyz, vec4f(newValue, 0f, 0f, 1f));
}

requires readonly_and_readwrite_storage_textures;

fn hash(value: u32) -> u32 {
{
var x = (value ^ (value >> 17u));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ describe('slime mold example', () => {
wrappedCallback(id.x, id.y, id.z);
}

requires readonly_and_readwrite_storage_textures;

@group(1) @binding(0) var oldState: texture_storage_2d<rgba8unorm, read>;

struct Params {
Expand Down Expand Up @@ -228,6 +230,8 @@ describe('slime mold example', () => {
textureStore(newState, gid.xy, vec4f(newColor, 1f));
}

requires readonly_and_readwrite_storage_textures;

fn hash(value: u32) -> u32 {
{
var x = (value ^ (value >> 17u));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ describe('uniformity test example', () => {
);

expect(shaderCodes).toMatchInlineSnapshot(`
"struct fullScreenTriangle_Output {
"requires readonly_and_readwrite_storage_textures;

struct fullScreenTriangle_Output {
@builtin(position) pos: vec4f,
@location(0) uv: vec2f,
}
Expand Down
3 changes: 3 additions & 0 deletions packages/typegpu/src/core/resolve/resolveData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ export function resolveData(ctx: ResolutionCtx, data: AnyData): string {
}

if (isWgslStorageTexture(data)) {
if (data.access !== 'write-only') {
ctx.requireFeatures.add('readonly_and_readwrite_storage_textures');
}
return `${data.type}<${data.format}, ${accessModeMap[data.access]}>`;
}

Expand Down
8 changes: 8 additions & 0 deletions packages/typegpu/src/resolutionCtx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import type {
StackLayer,
ShaderStage,
Wgsl,
WgslLanguageExtension,
} from './types.ts';
import { CodegenState, isSelfResolvable, NormalState, type FunctionArgument } from './types.ts';
import type { WgslEnableExtension } from './wgslExtensions.ts';
Expand Down Expand Up @@ -453,6 +454,7 @@ export class ResolutionCtxImpl implements ResolutionCtx {
// --

public readonly enableExtensions: WgslEnableExtension[] | undefined;
public readonly requireFeatures = new Set<WgslLanguageExtension>();
public expectedType: BaseData | undefined;

#usedImmediate: TgpuImmediateVar | undefined;
Expand All @@ -479,6 +481,7 @@ export class ResolutionCtxImpl implements ResolutionCtx {
);
}
this.#usedImmediate = immediate;
this.requireFeatures.add('immediate_address_space');
}

get usedImmediate(): TgpuImmediateVar | undefined {
Expand Down Expand Up @@ -1251,6 +1254,11 @@ export function resolve(item: Wgsl, options: ResolutionCtxImplOptions): Resoluti
code = `${extensions.join('\n')}\n\n${code}`;
}

if (ctx.requireFeatures.size > 0) {
const features = [...ctx.requireFeatures].join(', ');
code = `requires ${features};\n\n${code}`;
}

let declarations = ctx.declarations.map(({ name, code: declarationCode }) => ({
name,
code: bindingReplacements.reduce(
Expand Down
3 changes: 3 additions & 0 deletions packages/typegpu/src/tgsl/wgslGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2204,6 +2204,9 @@ ${stringifyNode(statement)}`);
expr,
asComptime(mutated.value.base) !== undefined,
);
if (mutated.value.components.length > 1) {
this.ctx.requireFeatures.add('swizzle_assignment');
}
} else {
throwIfImmutable(mutated.origin, expr, asComptime(mutated) !== undefined);
}
Expand Down
18 changes: 18 additions & 0 deletions packages/typegpu/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,23 @@ export class SimulationState {

export type ExecState = NormalState | CodegenState | SimulationState;

export type WgslLanguageExtension =
| 'readonly_and_readwrite_storage_textures'
| 'packed_4x8_integer_dot_product'
| 'unrestricted_pointer_parameters'
| 'pointer_composite_access'
| 'uniform_buffer_standard_layout'
| 'subgroup_id'
| 'subgroup_uniformity'
| 'texture_and_sampler_let'
| 'texture_formats_tier1'
| 'linear_indexing'
| 'immediate_address_space'
| 'fragment_depth'
| 'buffer_view'
| 'swizzle_assignment'
| 'atomic_vec2u_min_max';

/**
* Passed into each resolvable item. All items in a tree share a resolution ctx,
* but there can be layers added and removed from the item stack when going down
Expand All @@ -279,6 +296,7 @@ export interface ResolutionCtx {
readonly pre: string;
readonly mode: ExecState;
readonly enableExtensions: WgslEnableExtension[] | undefined;
readonly requireFeatures: Set<WgslLanguageExtension>;
readonly gen: ShaderGenerator;

/**
Expand Down
39 changes: 31 additions & 8 deletions packages/typegpu/tests/immediates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,31 @@ describe('tgpu.immediateVar', () => {
const fn1 = tgpu.fn([], d.f32)(() => level.$);

expect(tgpu.resolve([fn1])).toMatchInlineSnapshot(`
"var<immediate> level: f32;
"requires immediate_address_space;

var<immediate> level: f32;

fn fn1() -> f32 {
return level;
}"
`);
});

it('includes a require', () => {
const level = tgpu['~unstable'].immediateVar(d.f32);
const fn = tgpu.fn([], d.f32)(() => level.$);

expect(tgpu.resolve([fn])).toContain('requires immediate_address_space;');
});

it('does not emit the default value as an initializer', () => {
const level = tgpu['~unstable'].immediateVar(d.f32, 0.5);
const fn1 = tgpu.fn([], d.f32)(() => level.$);

expect(tgpu.resolve([fn1])).toMatchInlineSnapshot(`
"var<immediate> level: f32;
"requires immediate_address_space;

var<immediate> level: f32;

fn fn1() -> f32 {
return level;
Expand All @@ -62,7 +73,9 @@ describe('tgpu.immediateVar', () => {
});

expect(tgpu.resolve([fn1])).toMatchInlineSnapshot(`
"struct Params {
"requires immediate_address_space;

struct Params {
intensity: f32,
color: vec3f,
}
Expand All @@ -88,7 +101,9 @@ describe('tgpu.immediateVar', () => {
});

expect(tgpu.resolve([fn1])).toMatchInlineSnapshot(`
"var<immediate> offset: vec4f;
"requires immediate_address_space;

var<immediate> offset: vec4f;

fn fn1() -> vec2f {
let o = (&offset);
Expand Down Expand Up @@ -123,14 +138,18 @@ describe('tgpu.immediateVar', () => {
return slot.$ ? first.$ : second.$;
});
expect(tgpu.resolve([choose.with(slot, true)])).toMatchInlineSnapshot(`
"var<immediate> first: f32;
"requires immediate_address_space;

var<immediate> first: f32;

fn choose() -> f32 {
return first;
}"
`);
expect(tgpu.resolve([choose.with(slot, false)])).toMatchInlineSnapshot(`
"var<immediate> second: f32;
"requires immediate_address_space;

var<immediate> second: f32;

fn choose() -> f32 {
return second;
Expand All @@ -144,7 +163,9 @@ describe('tgpu.immediateVar', () => {
const outer = tgpu.fn([], d.f32)(() => inner() + level.$);

expect(tgpu.resolve([outer])).toMatchInlineSnapshot(`
"var<immediate> level: f32;
"requires immediate_address_space;

var<immediate> level: f32;

fn inner() -> f32 {
return level;
Expand Down Expand Up @@ -727,7 +748,9 @@ describe('tgpu.immediateVar', () => {
.with(level, levelImmediate);

expect(tgpu.resolve([fn1])).toMatchInlineSnapshot(`
"var<immediate> levelImmediate: f32;
"requires immediate_address_space;

var<immediate> levelImmediate: f32;

fn fn1() -> f32 {
return levelImmediate;
Expand Down
4 changes: 3 additions & 1 deletion packages/typegpu/tests/indent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ describe('indents', () => {
});

expect(tgpu.resolve([main])).toMatchInlineSnapshot(`
"@group(0) @binding(2) var<storage, read_write> counter: u32;
"requires readonly_and_readwrite_storage_textures;

@group(0) @binding(2) var<storage, read_write> counter: u32;

fn incrementCounter() {
counter += 1u;
Expand Down
4 changes: 3 additions & 1 deletion packages/typegpu/tests/namespace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ describe('tgpu.namespace', () => {
const fn = tgpu.fn([], d.f32)(() => level.$);

expect(tgpu.resolve([fn])).toMatchInlineSnapshot(`
"var<immediate> immediate_1: f32;
"requires immediate_address_space;

var<immediate> immediate_1: f32;

fn fn_1() -> f32 {
return immediate_1;
Expand Down
Loading
Loading