Skip to content
Open
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 @@ -173,9 +173,9 @@ describe('function visualizer example', () => {
return vec2f(0, 1);
}
let lineVertices = (&lineVertices_1);
let previous = (&(*lineVertices)[u32((index - 1f))]);
let current = (&(*lineVertices)[u32(index)]);
let next = (&(*lineVertices)[u32((index + 1f))]);
let previous = (&(*lineVertices)[i32((index - 1f))]);
let current = (&(*lineVertices)[i32(index)]);
let next = (&(*lineVertices)[i32((index + 1f))]);
let n1 = orthonormalForLine((*previous), (*current));
let n2 = orthonormalForLine((*current), (*next));
let avg = ((n1 + n2) / 2f);
Expand All @@ -196,7 +196,7 @@ describe('function visualizer example', () => {
let rightTop = ((*properties).transformation * vec4f(1, 1, 0, 1));
let canvasRatio = ((rightTop.x - leftBot.x) / (rightTop.y - leftBot.y));
let adjustedOffset = vec2f((offset.x / canvasRatio), offset.y);
return vertex_Output(vec4f(((*lineVertices)[u32(currentVertex)] + adjustedOffset), 0f, 1f));
return vertex_Output(vec4f(((*lineVertices)[i32(currentVertex)] + adjustedOffset), 0f, 1f));
}

@group(1) @binding(1) var<uniform> color: vec4f;
Expand Down
34 changes: 22 additions & 12 deletions packages/typegpu/src/tgsl/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ function getAutoConversionRank(src: BaseData, dest: BaseData): ConversionRankInf
return INFINITE_RANK;
}

const primitivePreference = {
f32: 0,
f16: 1,
i32: 2,
u32: 3,
bool: 4,
} as const;
type PrimitiveType = keyof typeof primitivePreference;

function getPreference(type: BaseData): number {
return primitivePreference[undecorate(type).type as PrimitiveType] ?? Number.POSITIVE_INFINITY;
}

function getImplicitConversionRank(src: BaseData, dest: BaseData): ConversionRankInfo {
const trueSrc = undecorate(src);
const trueDst = undecorate(dest);
Expand All @@ -103,15 +116,6 @@ function getImplicitConversionRank(src: BaseData, dest: BaseData): ConversionRan
return { rank: 1, action: 'ref' };
}

const primitivePreference = {
f32: 0,
f16: 1,
i32: 2,
u32: 3,
bool: 4,
} as const;
type PrimitiveType = keyof typeof primitivePreference;

if (trueSrc.type in primitivePreference && trueDst.type in primitivePreference) {
const srcType = trueSrc.type as PrimitiveType;
const destType = trueDst.type as PrimitiveType;
Expand Down Expand Up @@ -176,7 +180,9 @@ function findBestType(
uniqueTypes: BaseData[],
allowImplicit: boolean,
): ConversionResult | undefined {
let bestResult: { type: BaseData; details: ConversionRankInfo[]; sum: number } | undefined;
let bestResult:
| { type: BaseData; details: ConversionRankInfo[]; sum: number; preference: number }
| undefined;

for (const targetType of uniqueTypes) {
/**
Expand All @@ -196,8 +202,12 @@ function findBestType(
destType = conversion.targetType;
}
}
if (sum < (bestResult?.sum ?? Number.POSITIVE_INFINITY)) {
bestResult = { type: destType, details, sum };
const preference = getPreference(destType);
if (
sum < (bestResult?.sum ?? Number.POSITIVE_INFINITY) ||
(bestResult !== undefined && sum === bestResult.sum && preference < bestResult.preference)
) {
bestResult = { type: destType, details, sum, preference };
}
}
if (!bestResult) {
Expand Down
50 changes: 44 additions & 6 deletions packages/typegpu/tests/internal/getBestConversion.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect } from 'vitest';
import { abstractFloat, abstractInt } from '../../src/data/numeric.ts';
import { getBestConversion } from '../../src/tgsl/conversion.ts';
import type { BaseData } from '../../src/data/wgslTypes.ts';
import { it } from 'typegpu-testing-utility';
import { INTERNAL_createPtr } from '../../src/data/ptr.ts';
import { d } from '../../src/index.js';
Expand Down Expand Up @@ -67,22 +68,25 @@ describe('getBestConversion', () => {
// Potential targets (from input): u32, f16, i32
// Preference: f32(0) > f16(1) > i32(2) > u32(3)
//
// Rank of a cast is `destPref < srcPref ? 10 : 20`, summed over all sources.
// Equal sums are broken by preferring the lower destPref.
//
// Target f16 (pref 1):
// u32 (3) -> f16 (1): dest < src => rank 10
// u32 (3) -> f16 (1): destPref < srcPref => rank 10
// f16 (1) -> f16 (1): rank 0
// i32 (2) -> f16 (1): dest < src => rank 10
// i32 (2) -> f16 (1): destPref < srcPref => rank 10
// Total Rank = 10 + 0 + 10 = 20
//
// Target i32 (pref 2):
// u32 (3) -> i32 (2): dest < src => rank 10
// f16 (1) -> i32 (2): dest >= src => rank 20
// u32 (3) -> i32 (2): destPref < srcPref => rank 10
// f16 (1) -> i32 (2): destPref >= srcPref => rank 20
// i32 (2) -> i32 (2): rank 0
// Total Rank = 10 + 20 + 0 = 30
//
// Target u32 (pref 3):
// u32 (3) -> u32 (3): rank 0
// f16 (1) -> u32 (3): dest >= src => rank 20
// i32 (2) -> u32 (3): dest >= src => rank 20
// f16 (1) -> u32 (3): destPref >= srcPref => rank 20
// i32 (2) -> u32 (3): destPref >= srcPref => rank 20
// Total Rank = 0 + 20 + 20 = 40
//
// Lowest rank is 20 for target f16.
Expand Down Expand Up @@ -156,6 +160,40 @@ describe('getBestConversion', () => {
expect(res?.hasImplicitConversions).toBe(true);
});

it('does not depend on the order of targetTypes', () => {
const cases: { sources: BaseData[]; candidates: BaseData[]; expected: BaseData }[] = [
{ sources: [d.f32, d.f32], candidates: [d.i32, d.u32], expected: d.i32 },
{ sources: [d.f16], candidates: [d.i32, d.u32], expected: d.i32 },
{ sources: [d.bool], candidates: [d.i32, d.u32], expected: d.i32 },
{ sources: [d.u32, d.i32], candidates: [d.f32, d.f16], expected: d.f32 },
];

for (const { sources, candidates, expected } of cases) {
expect(getBestConversion(sources, candidates)?.targetType).toBe(expected);
expect(getBestConversion(sources, candidates.toReversed())?.targetType).toBe(expected);
}
});

it('does not depend on the order of sources', () => {
const cases: { sources: BaseData[]; expected: BaseData }[] = [
{ sources: [d.i32, d.u32, d.u32], expected: d.i32 },
{ sources: [d.f16, d.i32, d.i32], expected: d.f16 },
{ sources: [d.u32, d.f16, d.i32], expected: d.f16 },
];

for (const { sources, expected } of cases) {
expect(getBestConversion(sources)?.targetType).toBe(expected);
expect(getBestConversion(sources.toReversed())?.targetType).toBe(expected);
}
});

it('does not let preference outweigh the ranking as sources pile up', () => {
// u32: 0 + 4*10, f32: 10 + 4*10
expect(
getBestConversion([d.u32, d.bool, d.bool, d.bool, d.bool], [d.f32, d.u32])?.targetType,
).toBe(d.u32);
});

it('handles void gracefully', () => {
const resFail = getBestConversion([d.f32, d.Void]);
expect(resFail).toBeUndefined();
Expand Down
6 changes: 3 additions & 3 deletions packages/typegpu/tests/std/texture/textureGather.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ describe('textureGather', () => {
const component = 0i;
let gather2d = textureGather(component, tex2d, sampler_1, uv2d);
let gather2d_u32 = textureGather(component, tex2d_u32, sampler_1, uv2d);
let gather2d_array = textureGather(component, tex2d_array, sampler_1, uv2d, u32(idx));
let gathercube_array = textureGather(component, texcube_array, sampler_1, uv3d, u32(idx));
let gather2d_array = textureGather(component, tex2d_array, sampler_1, uv2d, i32(idx));
let gathercube_array = textureGather(component, texcube_array, sampler_1, uv3d, i32(idx));
let gatherdepth2d = textureGather(texdepth2d, sampler_1, uv2d);
let gatherdepth2d_array = textureGather(texdepth2d_array, sampler_1, uv2d, u32(idx));
let gatherdepth2d_array = textureGather(texdepth2d_array, sampler_1, uv2d, i32(idx));
}"
`);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/typegpu/tests/tgsl/conversion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ describe('convertToCommonType', () => {
expect(tgpu.resolve([fn])).toMatchInlineSnapshot(`
"fn fn_1() {
let arr = array<i32, 4>(1, 2, 3, 4);
let x = arr[1u];
let y = arr[1u];
let x = arr[1i];
let y = arr[1i];
let z = arr[1i];
let t = arr[1u];
}"
Expand Down
Loading