-
I had some working code and then I wanted to see if I could speed it up with workgroup memory. I'm using
Diff of changes that introduce the error: tombh/wrach@e693efe Log with `RUST_LOG=trace naga-cli physics.spv`:
Disassembled:
Cross-compiled to GLSL:#version 450
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
struct _22
{
vec2 _m0;
vec2 _m1;
uint _m2;
};
struct _23
{
uint _m0;
uint _m1;
};
struct _27
{
vec2 _m0;
vec2 _m1;
uvec2 _m2;
uint _m3;
uint _m4;
};
struct _37
{
uint _m0;
uint _m1;
bool _m2;
};
struct _40
{
uint _m0[];
uint _m1;
};
struct _41
{
vec2 _m0[];
uint _m1;
};
struct _42
{
_27 _m0;
_40 _m1;
_41 _m2;
_41 _m3;
_41 _m4;
_41 _m5;
_40 _m6;
vec2 _m7[1024];
vec2 _m8[1024];
uint _m9;
uint _m10;
bool _m11;
};
layout(binding = 0, std140) uniform _51_28
{
_27 _m0;
} _28;
layout(binding = 1, std430) buffer _53_29
{
uint _m0[];
} _29;
layout(binding = 2, std430) readonly buffer _55_30
{
vec2 _m0[];
} _30;
layout(binding = 3, std430) buffer _55_31
{
vec2 _m0[];
} _31;
layout(binding = 4, std430) readonly buffer _55_32
{
vec2 _m0[];
} _32;
layout(binding = 5, std430) buffer _55_33
{
vec2 _m0[];
} _33;
layout(binding = 6, std430) buffer _53_34
{
uint _m0[];
} _34;
layout(binding = 7, std430) readonly buffer _55_35
{
vec2 _m0[];
} _35;
layout(binding = 8, std430) readonly buffer _55_36
{
vec2 _m0[];
} _36;
shared vec2 _38[1024];
shared vec2 _39[1024];
_37 _85;
_23 _87;
uint _90;
void main()
{
uint _138;
uint _144 = gl_WorkGroupID.x * 64u;
uint _148 = _144 + gl_LocalInvocationID.x;
uint _149 = _148 + 1u;
bool _373;
uint _374;
if (gl_LocalInvocationID.x == 1u)
{
uint _123[4];
_123[0u] = 0u;
_123[1u] = 1u;
_123[2u] = _28._m0._m2.x;
_123[3u] = _28._m0._m2.x + 1u;
_37 _165;
_165 = _37(_144, _144 + 63u, false);
bool _1825;
uint _1826;
bool _1827;
uint _1828;
uint _1829;
_37 _166;
uint _168 = 0u;
uint _170 = 0u;
for (;;)
{
bool _182;
if (_165._m2)
{
_182 = true;
}
else
{
_182 = (_165._m0 <= _165._m1) != true;
}
_37 _202;
_23 _203;
if (_182)
{
_23 _186 = _87;
_186._m0 = 0u;
_202 = _165;
_203 = _186;
}
else
{
_37 _199;
if (_165._m0 < _165._m1)
{
_37 _196 = _165;
_196._m0 = _165._m0 + 1u;
_199 = _196;
}
else
{
_37 _197 = _165;
_197._m2 = true;
_199 = _197;
}
_202 = _199;
_203 = _23(1u, _165._m0);
}
bool _360;
bool _361;
uint _362;
bool _363;
_37 _364;
uint _365;
uint _366;
switch (int(_203._m0))
{
case 0:
{
_360 = false;
_361 = true;
_362 = _170;
_363 = false;
_364 = _85;
_365 = _90;
_366 = _90;
break;
}
case 1:
{
_23 _213;
_213 = _23(0u, 4u);
_23 _214;
uint _217;
uint _219;
bool _354;
bool _355;
_37 _356;
uint _357;
uint _358;
bool _359;
uint _216 = _168;
uint _218 = _170;
for (;;)
{
_23 _233;
_23 _234;
if (_213._m0 < _213._m1)
{
_23 _230 = _213;
_230._m0 = _213._m0 + 1u;
_233 = _230;
_234 = _23(1u, _213._m0);
}
else
{
_23 _232 = _87;
_232._m0 = 0u;
_233 = _213;
_234 = _232;
}
switch (int(_234._m0))
{
case 0:
{
_354 = false;
_355 = true;
_356 = _202;
_357 = _216;
_358 = _218;
_359 = false;
_214 = _87;
_217 = _90;
_219 = _90;
break;
}
case 1:
{
bool _349;
bool _350;
_23 _351;
uint _352;
uint _353;
if (_234._m1 < 4u)
{
uint _248 = _203._m1 + _123[_234._m1];
bool _344;
bool _345;
_23 _346;
uint _347;
uint _348;
if (_248 < uint(_34._m0.length()))
{
uint _255 = _248 + 1u;
bool _339;
bool _340;
_23 _341;
uint _342;
uint _343;
if (_255 < uint(_34._m0.length()))
{
uint _1823 = (_218 == 0u) ? _34._m0[_248] : _218;
_23 _271;
_271 = _23(_34._m0[_248], _34._m0[_255]);
_23 _272;
uint _275;
bool _333;
bool _334;
_23 _335;
uint _336;
uint _337;
bool _338;
uint _274 = _216;
for (;;)
{
_23 _289;
_23 _290;
if (_271._m0 < _271._m1)
{
_23 _286 = _271;
_286._m0 = _271._m0 + 1u;
_289 = _286;
_290 = _23(1u, _271._m0);
}
else
{
_23 _288 = _87;
_288._m0 = 0u;
_289 = _271;
_290 = _288;
}
switch (int(_290._m0))
{
case 0:
{
_333 = false;
_334 = true;
_335 = _233;
_336 = _274;
_337 = _1823;
_338 = false;
_272 = _87;
_275 = _90;
break;
}
case 1:
{
bool _330;
_23 _331;
uint _332;
if (_290._m1 < uint(_35._m0.length()))
{
bool _304 = _274 < 1024u;
bool _327;
_23 _328;
uint _329;
if (_304)
{
_38[_274] = _35._m0[_290._m1];
bool _324;
_23 _325;
uint _326;
if (_290._m1 < uint(_36._m0.length()))
{
_23 _322;
uint _323;
if (_304)
{
_39[_274] = _36._m0[_290._m1];
_322 = _289;
_323 = _274 + 1u;
}
else
{
_322 = _87;
_323 = _90;
}
_324 = _304 ? true : false;
_325 = _322;
_326 = _323;
}
else
{
_324 = false;
_325 = _87;
_326 = _90;
}
_327 = _324;
_328 = _325;
_329 = _326;
}
else
{
_327 = false;
_328 = _87;
_329 = _90;
}
_330 = _327;
_331 = _328;
_332 = _329;
}
else
{
_330 = false;
_331 = _87;
_332 = _90;
}
_333 = false;
_334 = false;
_335 = _87;
_336 = _90;
_337 = _90;
_338 = _330;
_272 = _331;
_275 = _332;
break;
}
default:
{
_333 = true;
_334 = false;
_335 = _87;
_336 = _90;
_337 = _90;
_338 = false;
_272 = _87;
_275 = _90;
break;
}
}
if (_338)
{
_271 = _272;
_274 = _275;
continue;
}
else
{
break;
}
}
_339 = _333;
_340 = _334;
_341 = _335;
_342 = _336;
_343 = _337;
}
else
{
_339 = false;
_340 = false;
_341 = _87;
_342 = _90;
_343 = _90;
}
_344 = _339;
_345 = _340;
_346 = _341;
_347 = _342;
_348 = _343;
}
else
{
_344 = false;
_345 = false;
_346 = _87;
_347 = _90;
_348 = _90;
}
_349 = _344;
_350 = _345;
_351 = _346;
_352 = _347;
_353 = _348;
}
else
{
_349 = false;
_350 = false;
_351 = _87;
_352 = _90;
_353 = _90;
}
_354 = _349;
_355 = false;
_356 = _85;
_357 = _90;
_358 = _90;
_359 = _350;
_214 = _351;
_217 = _352;
_219 = _353;
break;
}
default:
{
_354 = true;
_355 = false;
_356 = _85;
_357 = _90;
_358 = _90;
_359 = false;
_214 = _87;
_217 = _90;
_219 = _90;
break;
}
}
if (_359)
{
_213 = _214;
_216 = _217;
_218 = _219;
continue;
}
else
{
break;
}
}
_360 = _354;
_361 = false;
_362 = _90;
_363 = _355;
_364 = _356;
_365 = _357;
_366 = _358;
break;
}
default:
{
_360 = true;
_361 = false;
_362 = _90;
_363 = false;
_364 = _85;
_365 = _90;
_366 = _90;
break;
}
}
if (_360)
{
_166 = _85;
}
else
{
_166 = _364;
}
_1825 = _360 ? false : _361;
_1826 = _360 ? _90 : _362;
_1827 = _360 ? false : _363;
_1828 = _360 ? _90 : _365;
_1829 = _360 ? _90 : _366;
if (_1827)
{
_165 = _166;
_168 = _1828;
_170 = _1829;
continue;
}
else
{
break;
}
}
_373 = _1825;
_374 = _1826;
}
else
{
_373 = true;
_374 = 0u;
}
if (_373)
{
barrier();
uint _404 = _28._m0._m2.x * _28._m0._m2.y;
if (_149 > _404)
{
}
else
{
bool _413 = _149 == _404;
uint _440 = _148 + 2u;
uint _446 = _29._m0[_149] + (_29._m0[_440] - _29._m0[_149]);
uint _500 = _148 + 3u;
uint _524 = _149 + (_28._m0._m2.x + 2u);
uint _530 = _524 + 1u;
uint _566 = _34._m0[_530] + (_34._m0[_524 + 2u] - _34._m0[_530]);
uint _568 = 16u - _374;
_22 _1513[8] = _22[](_22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u), _22(vec2(0.0), vec2(0.0), 0u));
uint _586 = _446 - _29._m0[_149];
uint _1830 = (_586 > 4u) ? 4u : _586;
_23 _598;
_598 = _23(_29._m0[_149], _29._m0[_149] + _1830);
_23 _599;
uint _602;
bool _1166;
uint _601 = 0u;
for (;;)
{
_23 _616;
_23 _617;
if (_598._m0 < _598._m1)
{
_23 _613 = _598;
_613._m0 = _598._m0 + 1u;
_616 = _613;
_617 = _23(1u, _598._m0);
}
else
{
_23 _615 = _87;
_615._m0 = 0u;
_616 = _598;
_617 = _615;
}
switch (int(_617._m0))
{
case 0:
{
uint _631 = _566 - _34._m0[_530];
_23 _643;
_643 = _23(_34._m0[_530], _34._m0[_530] + ((_631 > 4u) ? 4u : _631));
_23 _644;
uint _647;
bool _1157;
uint _646 = _568;
for (;;)
{
_23 _661;
_23 _662;
if (_643._m0 < _643._m1)
{
_23 _658 = _643;
_658._m0 = _643._m0 + 1u;
_661 = _658;
_662 = _23(1u, _643._m0);
}
else
{
_23 _660 = _87;
_660._m0 = 0u;
_661 = _643;
_662 = _660;
}
switch (int(_662._m0))
{
case 0:
{
_22 _1520[8] = _1513;
_23 _1348 = _23(0u, _1830);
_23 _1350;
_1350 = _1348;
bool _1833;
_23 _1420;
for (;;)
{
_23 _1363;
_23 _1364;
if (_1350._m0 < _1350._m1)
{
_23 _1360 = _1350;
_1360._m0 = _1350._m0 + 1u;
_1363 = _1360;
_1364 = _23(1u, _1350._m0);
}
else
{
_23 _1356 = _87;
_1356._m0 = 0u;
_1363 = _1350;
_1364 = _1356;
}
bool _1413;
bool _1414;
_23 _1415;
switch (int(_1364._m0))
{
case 0:
{
_1413 = false;
_1414 = false;
_1415 = _87;
break;
}
case 1:
{
_23 _1374;
_1374 = _23(_1364._m1 + 1u, _1830);
bool _1403;
bool _1404;
_23 _1405;
bool _1406;
_23 _1407;
for (;;)
{
_23 _1387;
_23 _1388;
if (_1374._m0 < _1374._m1)
{
_23 _1384 = _1374;
_1384._m0 = _1374._m0 + 1u;
_1387 = _1384;
_1388 = _23(1u, _1374._m0);
}
else
{
_23 _1380 = _87;
_1380._m0 = 0u;
_1387 = _1374;
_1388 = _1380;
}
switch (int(_1388._m0))
{
case 0:
{
_1403 = false;
_1404 = true;
_1405 = _1363;
_1406 = false;
_1407 = _87;
break;
}
case 1:
{
vec2 _1428 = _1520[_1364._m1]._m0;
vec2 _1432 = _1520[_1388._m1]._m0;
float _1435 = _1428.x - _1432.x;
float _1438 = _1428.y - _1432.y;
float _1442 = sqrt(fma(_1435, _1435, _1438 * _1438));
float _1832 = (_1442 == 0.0) ? 9.9999997473787516355514526367188e-05 : _1442;
if (_1832 > 1.0)
{
}
else
{
float _1451 = (0.5 * (1.0 - _1832)) / _1832;
vec2 _1455 = _1520[_1388._m1]._m0;
vec2 _1459 = _1520[_1364._m1]._m0;
float _1462 = _1455.x - _1459.x;
float _1465 = _1455.y - _1459.y;
_1520[_1364._m1]._m0.x = fma(-_1462, _1451, _1520[_1364._m1]._m0.x);
_1520[_1364._m1]._m0.y = fma(-_1465, _1451, _1520[_1364._m1]._m0.y);
_1520[_1388._m1]._m0.x = fma(_1462, _1451, _1520[_1388._m1]._m0.x);
_1520[_1388._m1]._m0.y = fma(_1465, _1451, _1520[_1388._m1]._m0.y);
}
_1403 = false;
_1404 = false;
_1405 = _87;
_1406 = true;
_1407 = _1387;
break;
}
default:
{
_1403 = true;
_1404 = false;
_1405 = _87;
_1406 = false;
_1407 = _87;
break;
}
}
if (_1406)
{
_1374 = _1407;
continue;
}
else
{
break;
}
}
_1413 = _1403;
_1414 = _1404;
_1415 = _1405;
break;
}
default:
{
_1413 = true;
_1414 = false;
_1415 = _87;
break;
}
}
if (_1413)
{
_1420 = _87;
}
else
{
_1420 = _1415;
}
_1833 = _1413 ? false : _1414;
if (_1833)
{
_1350 = _1420;
continue;
}
else
{
break;
}
}
_23 _680;
_680 = _1348;
_23 _681;
bool _1148;
for (;;)
{
_23 _696;
_23 _697;
if (_680._m0 < _680._m1)
{
_23 _693 = _680;
_693._m0 = _680._m0 + 1u;
_696 = _693;
_697 = _23(1u, _680._m0);
}
else
{
_23 _695 = _87;
_695._m0 = 0u;
_696 = _680;
_697 = _695;
}
switch (int(_697._m0))
{
case 0:
{
uint _711 = _29._m0[_149] + 4u;
bool _878;
if (_446 <= _711)
{
_878 = true;
}
else
{
_23 _718;
_718 = _23(_711, _446);
_23 _719;
bool _876;
bool _877;
for (;;)
{
_23 _734;
_23 _735;
if (_718._m0 < _718._m1)
{
_23 _731 = _718;
_731._m0 = _718._m0 + 1u;
_734 = _731;
_735 = _23(1u, _718._m0);
}
else
{
_23 _733 = _87;
_733._m0 = 0u;
_734 = _718;
_735 = _733;
}
switch (int(_735._m0))
{
case 0:
{
_876 = true;
_877 = false;
_719 = _87;
break;
}
case 1:
{
float _1494 = _30._m0[_735._m1].x + _32._m0[_735._m1].x;
vec2 _1821 = vec2(_1494, _30._m0[_735._m1].y + _32._m0[_735._m1].y);
float _763 = _28._m0._m1.x + _28._m0._m0.x;
float _769 = _28._m0._m1.y + _28._m0._m0.y;
vec2 _1723;
vec2 _1724;
if (_1494 > _763)
{
vec2 _1692 = _1821;
_1692.x = _763;
vec2 _1695 = _32._m0[_735._m1];
_1695.x = _32._m0[_735._m1].x * (-1.0);
_1724 = _1695;
_1723 = _1692;
}
else
{
_1724 = _32._m0[_735._m1];
_1723 = _1821;
}
vec2 _1725;
vec2 _1726;
if (_1723.x < _28._m0._m1.x)
{
vec2 _1698 = _1723;
_1698.x = _28._m0._m1.x;
vec2 _1701 = _1724;
_1701.x = _1724.x * (-1.0);
_1726 = _1701;
_1725 = _1698;
}
else
{
_1726 = _1724;
_1725 = _1723;
}
vec2 _1727;
vec2 _1728;
if (_1725.y > _769)
{
vec2 _1704 = _1725;
_1704.y = _769;
vec2 _1707 = _1726;
_1707.y = _1726.y * (-1.0);
_1728 = _1707;
_1727 = _1704;
}
else
{
_1728 = _1726;
_1727 = _1725;
}
vec2 _1729;
vec2 _1738;
if (_1727.y < _28._m0._m1.y)
{
vec2 _1710 = _1727;
_1710.y = _28._m0._m1.y;
vec2 _1713 = _1728;
_1713.y = _1728.y * (-1.0);
_1738 = _1710;
_1729 = _1713;
}
else
{
_1738 = _1727;
_1729 = _1728;
}
float _1838 = (_1729.x < (-1.0)) ? (-1.0) : _1729.x;
float _1840 = (_1729.y < (-1.0)) ? (-1.0) : _1729.y;
_31._m0[_735._m1] = _1738;
_33._m0[_735._m1] = vec2((_1838 > 1.0) ? 1.0 : _1838, (_1840 > 1.0) ? 1.0 : _1840);
_876 = false;
_877 = true;
_719 = _734;
break;
}
default:
{
_876 = false;
_877 = false;
_719 = _87;
break;
}
}
if (_877)
{
_718 = _719;
continue;
}
else
{
break;
}
}
_878 = _876;
}
if (_878)
{
_29._m0[_149] = 0u;
_34._m0[_149] = 0u;
bool _935;
if (_413)
{
_935 = true;
}
else
{
bool _894 = _28._m0._m2.x == 0u;
bool _934;
if (_894)
{
_934 = false;
}
else
{
bool _933;
if (_894)
{
_933 = false;
}
else
{
if ((_149 % _28._m0._m2.x) == (_28._m0._m2.x - 1u))
{
_34._m0[_440] = 0u;
}
else
{
}
bool _915 = _28._m0._m2.y == 0u;
if (_915)
{
}
else
{
if ((_149 / _28._m0._m2.y) == (_28._m0._m2.y - 1u))
{
_34._m0[_149 + _28._m0._m2.x] = 0u;
}
else
{
}
}
_933 = _915 ? false : true;
}
_934 = _933;
}
_935 = _934;
}
if (_935)
{
if (_413)
{
_29._m0[_440] = 0u;
_34._m0[_440] = 0u;
if (_413)
{
}
else
{
bool _955 = _28._m0._m2.x == 0u;
if (_955)
{
}
else
{
if (_955)
{
}
else
{
if ((_440 % _28._m0._m2.x) == (_28._m0._m2.x - 1u))
{
_34._m0[_500] = 0u;
}
else
{
}
if (_28._m0._m2.y == 0u)
{
}
else
{
if ((_440 / _28._m0._m2.y) == (_28._m0._m2.y - 1u))
{
_34._m0[_440 + _28._m0._m2.x] = 0u;
}
else
{
}
}
}
}
}
}
else
{
}
}
else
{
}
}
else
{
}
_1148 = false;
_681 = _87;
break;
}
case 1:
{
vec2 _1011 = _1520[_697._m1]._m1;
_1520[_697._m1]._m0.x += _1011.x;
_1520[_697._m1]._m0.y += _1011.y;
float _1034 = _28._m0._m1.x + _28._m0._m0.x;
float _1040 = _28._m0._m1.y + _28._m0._m0.y;
if (_1520[_697._m1]._m0.x > _1034)
{
_1520[_697._m1]._m0.x = _1034;
_1520[_697._m1]._m1.x *= (-1.0);
}
else
{
}
if (_1520[_697._m1]._m0.x < _28._m0._m1.x)
{
_1520[_697._m1]._m0.x = _28._m0._m1.x;
_1520[_697._m1]._m1.x *= (-1.0);
}
else
{
}
if (_1520[_697._m1]._m0.y > _1040)
{
_1520[_697._m1]._m0.y = _1040;
_1520[_697._m1]._m1.y *= (-1.0);
}
else
{
}
if (_1520[_697._m1]._m0.y < _28._m0._m1.y)
{
_1520[_697._m1]._m0.y = _28._m0._m1.y;
_1520[_697._m1]._m1.y *= (-1.0);
}
else
{
}
float _1834 = (_1520[_697._m1]._m1.x < (-1.0)) ? (-1.0) : _1520[_697._m1]._m1.x;
_1520[_697._m1]._m1.x = (_1834 > 1.0) ? 1.0 : _1834;
float _1836 = (_1520[_697._m1]._m1.y < (-1.0)) ? (-1.0) : _1520[_697._m1]._m1.y;
_1520[_697._m1]._m1.y = (_1836 > 1.0) ? 1.0 : _1836;
_31._m0[_1520[_697._m1]._m2] = _1520[_697._m1]._m0;
_33._m0[_1520[_697._m1]._m2] = _1520[_697._m1]._m1;
_1148 = true;
_681 = _696;
break;
}
default:
{
_1148 = false;
_681 = _87;
break;
}
}
if (_1148)
{
_680 = _681;
continue;
}
else
{
break;
}
}
_1157 = false;
_644 = _87;
_647 = _90;
break;
}
case 1:
{
_1513[_646] = _22(_38[_662._m1], _39[_662._m1], _662._m1);
_1157 = true;
_644 = _661;
_647 = _646 + 1u;
break;
}
default:
{
_1157 = false;
_644 = _87;
_647 = _90;
break;
}
}
if (_1157)
{
_643 = _644;
_646 = _647;
continue;
}
else
{
break;
}
}
_1166 = false;
_599 = _87;
_602 = _90;
break;
}
case 1:
{
_1513[_601] = _22(_30._m0[_617._m1], _32._m0[_617._m1], _617._m1);
_1166 = true;
_599 = _616;
_602 = _601 + 1u;
break;
}
default:
{
_1166 = false;
_599 = _87;
_602 = _90;
break;
}
}
if (_1166)
{
_598 = _599;
_601 = _602;
continue;
}
else
{
break;
}
}
}
}
else
{
}
}
Does anybody have any tips for how to start to debug this. My diff is quite big and it's hard to turn certain parts of it off and on. |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 7 replies
-
That indeed looks tricky. Is your shader open source? Also you can try enabling all logging - |
Beta Was this translation helpful? Give feedback.
-
I am hitting a similar problem @tombh - what did you use to cross compile your |
Beta Was this translation helpful? Give feedback.
-
Also, resolving this issue should improve our experience as well gfx-rs/wgpu#6363. |
Beta Was this translation helpful? Give feedback.
-
I've managed to get a minimal reproducible Rust shader: #![cfg_attr(target_arch = "spirv", no_std)]
use spirv_std::{glam::Vec2, spirv};
type Workgroup = [Vec2; 1];
pub struct Cell<'world> {
pub positions: &'world mut [Vec2],
pub velocities: &'world [Vec2],
pub workgroup: &'world mut Workgroup,
}
impl Cell<'_> {
pub fn physics_for_cell(&mut self) {
self.workgroup[0] = self.velocities[0];
self.positions[0] = self.workgroup[0];
}
}
#[spirv(compute(threads(1)))]
pub fn main(
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] positions: &mut [Vec2],
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] velocities: &[Vec2],
#[spirv(workgroup)] workgroup: &mut Workgroup,
) {
let mut cell = Cell {
positions,
velocities,
workgroup,
};
cell.physics_for_cell();
} And so the validation error now is:
How do I dump the Naga representation? Would that be an internal WGSL version? Here's the GLSL version from GLSL: #version 450
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
struct _5
{
vec2 _m0[];
uint _m1;
};
struct _6
{
_5 _m0;
_5 _m1;
vec2 _m2[1];
};
layout(binding = 0, std430) buffer _9_3
{
vec2 _m0[];
} _3;
layout(binding = 1, std430) readonly buffer _9_4
{
vec2 _m0[];
} _4;
shared vec2 _7[1];
void main()
{
if (0u < uint(_4._m0.length()))
{
_7[0u] = _4._m0[0u];
if (0u < uint(_3._m0.length()))
{
_3._m0[0u] = _7[0u];
}
else
{
}
}
else
{
}
} And here's the SPIR-V: ; SPIR-V
; Version: 1.3
; Generator: Google rspirv; 0
; Bound: 56
; Schema: 0
OpCapability Shader
OpMemoryModel Logical Simple
OpEntryPoint GLCompute %1 "main"
OpExecutionMode %1 LocalSize 1 1 1
OpDecorate %_runtimearr_v2float ArrayStride 8
OpDecorate %_struct_9 Block
OpMemberDecorate %_struct_9 0 Offset 0
OpDecorate %3 Binding 0
OpDecorate %3 DescriptorSet 0
OpDecorate %4 NonWritable
OpDecorate %4 Binding 1
OpDecorate %4 DescriptorSet 0
OpMemberDecorate %_struct_5 0 Offset 0
OpMemberDecorate %_struct_5 1 Offset 4
OpDecorate %_arr_v2float_uint_1 ArrayStride 8
OpMemberDecorate %_struct_6 0 Offset 0
OpMemberDecorate %_struct_6 1 Offset 8
OpMemberDecorate %_struct_6 2 Offset 16
%void = OpTypeVoid
%12 = OpTypeFunction %void
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%_runtimearr_v2float = OpTypeRuntimeArray %v2float
%_ptr_StorageBuffer__runtimearr_v2float = OpTypePointer StorageBuffer %_runtimearr_v2float
%_struct_9 = OpTypeStruct %_runtimearr_v2float
%_ptr_StorageBuffer__struct_9 = OpTypePointer StorageBuffer %_struct_9
%3 = OpVariable %_ptr_StorageBuffer__struct_9 StorageBuffer
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%4 = OpVariable %_ptr_StorageBuffer__struct_9 StorageBuffer
%_struct_5 = OpTypeStruct %_ptr_StorageBuffer__runtimearr_v2float %uint
%uint_1 = OpConstant %uint 1
%_arr_v2float_uint_1 = OpTypeArray %v2float %uint_1
%_ptr_Workgroup__arr_v2float_uint_1 = OpTypePointer Workgroup %_arr_v2float_uint_1
%_struct_6 = OpTypeStruct %_struct_5 %_struct_5 %_ptr_Workgroup__arr_v2float_uint_1
%7 = OpVariable %_ptr_Workgroup__arr_v2float_uint_1 Workgroup
%bool = OpTypeBool
%_ptr_StorageBuffer_v2float = OpTypePointer StorageBuffer %v2float
%_ptr_Workgroup_v2float = OpTypePointer Workgroup %v2float
%1 = OpFunction %void None %12
%25 = OpLabel
%26 = OpAccessChain %_ptr_StorageBuffer__runtimearr_v2float %3 %uint_0
%27 = OpArrayLength %uint %3 0
%28 = OpAccessChain %_ptr_StorageBuffer__runtimearr_v2float %4 %uint_0
%29 = OpArrayLength %uint %4 0
%53 = OpCompositeConstruct %_struct_5 %26 %27
%54 = OpCompositeConstruct %_struct_5 %28 %29
%55 = OpCompositeConstruct %_struct_6 %53 %54 %7
%36 = OpULessThan %bool %uint_0 %29
OpSelectionMerge %37 None
OpBranchConditional %36 %38 %39
%38 = OpLabel
%41 = OpInBoundsAccessChain %_ptr_StorageBuffer_v2float %28 %uint_0
%42 = OpLoad %v2float %41
%43 = OpInBoundsAccessChain %_ptr_Workgroup_v2float %7 %uint_0
OpStore %43 %42
%45 = OpLoad %v2float %43
%47 = OpULessThan %bool %uint_0 %27
OpSelectionMerge %48 None
OpBranchConditional %47 %49 %50
%49 = OpLabel
%52 = OpInBoundsAccessChain %_ptr_StorageBuffer_v2float %26 %uint_0
OpStore %52 %45
OpBranch %48
%50 = OpLabel
OpBranch %48
%48 = OpLabel
OpBranch %37
%39 = OpLabel
OpBranch %37
%37 = OpLabel
OpReturn
OpFunctionEnd I've made a discussion on the |
Beta Was this translation helpful? Give feedback.
-
This is the function I use in my tests to validate SPIR-V shaders: /// Validate an SPIR-V ".spv" binary
fn validate_src(path: &std::path::PathBuf) {
log::info!("validating source");
log::info!(" reading '{}'", path.display());
let bytes = std::fs::read(path).unwrap();
log::info!(" {:0.2}k bytes read", bytes.len() as f32 / 1000.0);
let opts = naga::front::spv::Options::default();
let module = match naga::front::spv::parse_u8_slice(&bytes, &opts) {
Ok(m) => m,
Err(e) => {
log::error!("{e}");
panic!("SPIR-V parse error");
}
};
log::info!(" SPIR-V parsed");
let mut validator =
naga::valid::Validator::new(Default::default(), naga::valid::Capabilities::empty());
let is_valid;
let info = match validator.validate(&module) {
Ok(i) => {
is_valid = true;
log::info!(" SPIR-V validated");
i
}
Err(e) => {
log::error!("{}", e.emit_to_string(""));
is_valid = false;
let mut validator = naga::valid::Validator::new(
ValidationFlags::empty(),
naga::valid::Capabilities::empty(),
);
validator.validate(&module).unwrap()
}
};
let wgsl = naga::back::wgsl::write_string(
&module,
&info,
naga::back::wgsl::WriterFlags::empty(),
)
.unwrap();
log::info!(" output WGSL generated");
let print_var_name = path
.file_stem()
.unwrap()
.to_str()
.unwrap()
.replace('-', "_");
let maybe_output_path = if std::env::var("print_wgsl").is_ok() || !is_valid {
let dir = std::path::PathBuf::from("../../test_output");
std::fs::create_dir_all(&dir).unwrap();
let output_path = dir.join(print_var_name).with_extension("wgsl");
log::info!("writing WGSL to '{}'", output_path.display());
Some(output_path)
} else {
log::info!(" to save the generated WGSL, use an env var 'print_wgsl=1'");
None
};
if let Some(output_path) = maybe_output_path {
std::fs::write(&output_path, &wgsl).unwrap();
log::info!(" wrote generated WGSL to {}", output_path.display());
}
if !is_valid {
panic!("SPIR-V validation error");
}
let module = match naga::front::wgsl::parse_str(&wgsl) {
Ok(m) => m,
Err(e) => {
log::error!("{}", e.emit_to_string(&wgsl));
panic!("wgsl parse error");
}
};
log::info!(" output WGSL parsed");
let mut validator =
naga::valid::Validator::new(Default::default(), naga::valid::Capabilities::empty());
let _info = match validator.validate(&module) {
Ok(i) => i,
Err(e) => {
log::error!("{}", e.emit_to_string(&wgsl));
panic!("wgsl validation error");
}
};
log::info!(" wgsl output validated");
} That will attempt to parse and validate the shader. If the shader doesn't validate, it will try to re-validate with "very relaxed rules", aka none, and then print the WGSL that the module produces, which does often help. Actually dumping the module is possible by using its |
Beta Was this translation helpful? Give feedback.
-
Nice! Is it okay that I added your code, with accreditation, to my standalone rust-gpu compiler? https://github.com/tombh/rust-gpu-compiler/blob/main/src/validate.rs But it turns out that even the second re-validation with empty validation flags causes the same validation error, so I can't print out the cross-compiled WGSL 😞 |
Beta Was this translation helpful? Give feedback.
-
Finally got to the bottom of it! Note that it's Also note that |
Beta Was this translation helpful? Give feedback.
Finally got to the bottom of it!
naga
doesn't support pointers in structs gfx-rs/wgpu#6623Note that it's
naga
(which is merely a linter/validator) that doesn't support pointers in structs.rust-gpu
does support pointers in structs. Andnaga
can be easily avoided withwgpu
'swgpu::Features::SPIRV_SHADER_PASSTHROUGH
.Also note that
rust-gpu
doesn't always convert a Rust pointer in a struct to a SPIRV pointer in a struct. It often compiles away pointers in structs for efficiency.