Sergio0694 / ComputeSharp

A .NET library to run C# code in parallel on the GPU through DX12, D2D1, and dynamically generated HLSL compute and pixel shaders, with the goal of making GPU computing easy to use for all .NET developers! 🚀
MIT License
2.7k stars 121 forks source link

Wild idea: `Hlsl.Escape<T>("...")` #736

Closed rickbrew closed 8 months ago

rickbrew commented 8 months ago

I had this idea after thinking about https://github.com/Sergio0694/ComputeSharp/issues/735 some more

What if there was a method like,

public static class Hlsl
{
    public static T Escape<T>(string expression);
}

You could use it in a shader like so:

bool4 selector = ...;
float4 values1 = ...;
float4 values2 = ...;
float4 result = Hlsl.Escape<float4>("selector ? values1 : values2");

This would permit experimenting with various HLSL expressions that cannot currently be expressed using ComputeSharp at all. Instead of asking for functionality and then testing it out, I could test it out ad-hoc and then ask for it to be added officially.

rickbrew commented 8 months ago

Could also have this for a field so I could play around with other HLSL constructs like samplers

// this is just copying a regular resource texture definition, but imagine I change it somehow, or add parameters to the SamplerState, etc.
[HlslEscape("""
    Texture1D<float> resTex2 : register(t2);
    SamplerState __sampler__rexTex2 : register(s2);
    """)] 
private readonly int _ignored;

There are some mysteries around things like LODs and mipmaps that we can't really solve unless I do a bunch of experimentation, and this would enablle me to do that

Sergio0694 commented 8 months ago

I understand the scenario, which is absolutely valid, and it is one I definitely want to support. However, support for this is already in place, but it's not using this design. The issue with something like this is that it requires significant work, it's not really extensible, and it's quite error prone and leaking implementation details. I would have to design and implement a whole new system to do these in-place substitutions, and like you also mentioned, maybe just Hlsl.Escape wouldn't be enough, what if I also wanted a standalone statement, or what if I also wanted to manually define a field, or maybe a macro, etc. It gets out of hand pretty easily. Additionally, I'm doing all sorts of rewriting and renaming of things in HLSL, and it's not guaranteed that eg. the variables you'd be referring to from Hlsl.Escape would have the same name, potentially leading to hard to understand errors.

That said, as I said you can already do this. This is actually part of the reason why the shader descriptors have been designed this way. You can just not use [D2DGeneratedPixelShaderDescriptor], and write your own descriptor, with your fully custom HLSL. You can easily piggyback the other D2D1PixelShader APIs to compile the shader, etc., and you could even define a dummy shader with a generated descriptor, and no HLSL, to have all the metadata being annotated there, and then you can have your descriptor simply proxy all of those methods through that when needed (eg. for marshalling that can be very useful, as there's a fair amount of complexity there). Hope this makes sense 🙂