-
Notifications
You must be signed in to change notification settings - Fork 33
Description
Problem
The current system for main entrypoints has a number of issues:
imageMain
andprintMain
must be inuser.slang
(not a problem for the website, but is for the extension)- They obscure functionality from the user
- They require extra code to handle
imageMain
doesn't allow writing to arbitrary locations, which makes things like only drawing to part of the screen harder(ex. drawing particles)- They can't be used at the same time, meaning you can't use print statements to debug image shaders
- They require unnecessary bind slots. The print buffer is always bound in image shaders, and the outputTexture is always bound in print shaders, even though they are unused. This can eat up the webgpu bind limits, thereby preventing the user from doing some complex shaders.
Proposal
Introduce printing.slang
and render.slang
. These would be imported by the user when necessary and would bind their own requirements.
Printing functionality (g_printBufferIndex
, g_printedBuffer
, IPrintF
, etc.) currently in playground.slang
would move to printing.slang
.
Render functionality (mostly outputTexture
) would move to render.slang
. The special functionality of imageMain
(getting the render size, discarding threads outside it, and writing to the output) could be provided by a function drawPixel
that takes a lambda.
Examples
Print shader
import playground;
import printing;
[shader("compute")]
[numthreads(1, 1, 1)]
[playground::CALL(1, 1, 1)]
[playground::CALL::ONCE]
void printMain()
{
print("%d, %3.2d, 0x%x, %8.3f, %s, %e\n", 2, 3456, 2134, 40.1234, "hello world", 12.547);
}
Image shader
import playground;
import render;
[shader("compute")]
[numthreads(16, 16, 1)]
[playground::CALL::SIZE_OF("outputTexture")]
void imageMain(uint2 dispatchThreadID : SV_DispatchThreadID)
{
drawPixel(dispatchThreadID, (uint2 screenSize) => {
return float4(0.3, 0.7, 0.55, 1.0);
});
}
Downsides
This would require specifying more information in all current example shaders. For print shaders users have to include:
[shader("compute")]
[numthreads(1, 1, 1)]
[playground::CALL(1, 1, 1)]
[playground::CALL::ONCE]
Which is boilerplate. However, this also arguably makes the playground easier to learn, and makes it more clear what print shaders are actually doing.
Translated imageMain
shaders would need to reference outputTexture
in their boilerplate, and the lack of clear definition of outputTexture
in user visible code could cause confusion. In addition, drawPixel
would add an extra indentation level.
UI would also have to be altered to support printing and rendering at the same time.
Alternatives
Add RENDER_RESULT
attribute, do not use render.slang
We could create an attribute that allows setting any texture as the render result. In this case, users would have to implement the special functionality of imageMain
themselves, which would be extra boilerplate but could be more comprehensible. We could also do this in addition to offering render.slang
and use it to implement render.slang
without special logic. It would also potentially require extra logic for rendering non-screen size output textures.
Add PRINT_RESULT
attribute, do not use printing.slang
We could have the user include current printing logic in their shaders. This would add a lot of boilerplate to every print shader, which would make how printing works more understandable. It would crowd out what shaders are actually trying to do/show with logic that can be abstracted away.