AskingQuestions / Shadeup

A language for WebGPU that makes writing shaders easier
https://shadeup.dev
137 stars 4 forks source link

No issue : Add internal texture and uniform params to ComputeShader_rt #2

Open colinbouvry opened 1 year ago

colinbouvry commented 1 year ago

Hello

// texture Texture2D readTex; RWTexture2D writeTex; // uniform params int range; uint threshold; uint nstates; bool moore; int rez; float4 colors[21];

Do you have idea to add this feature ?

Thanks

AskingQuestions commented 1 year ago

There's a section in the Main compute shader c++ file that looks like this:

BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
/*
* Here's where you define one or more of the input parameters for your shader.
* Some examples:
*/
// SHADER_PARAMETER(uint32, MyUint32) // On the shader side: uint32 MyUint32;
// SHADER_PARAMETER(FVector3f, MyVector) // On the shader side: float3 MyVector;

// SHADER_PARAMETER_TEXTURE(Texture2D, MyTexture) // On the shader side: Texture2D<float4> MyTexture; (float4 should be whatever you expect each pixel in the texture to be, in this case float4(R,G,B,A) for 4 channels)
// SHADER_PARAMETER_SAMPLER(SamplerState, MyTextureSampler) // On the shader side: SamplerState MySampler; // CPP side: TStaticSamplerState<ESamplerFilter::SF_Bilinear>::GetRHI();

// SHADER_PARAMETER_ARRAY(float, MyFloatArray, [3]) // On the shader side: float MyFloatArray[3];

// SHADER_PARAMETER_UAV(RWTexture2D<FVector4f>, MyTextureUAV) // On the shader side: RWTexture2D<float4> MyTextureUAV;
// SHADER_PARAMETER_UAV(RWStructuredBuffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: RWStructuredBuffer<FMyCustomStruct> MyCustomStructs;
// SHADER_PARAMETER_UAV(RWBuffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: RWBuffer<FMyCustomStruct> MyCustomStructs;

// SHADER_PARAMETER_SRV(StructuredBuffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: StructuredBuffer<FMyCustomStruct> MyCustomStructs;
// SHADER_PARAMETER_SRV(Buffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: Buffer<FMyCustomStruct> MyCustomStructs;
// SHADER_PARAMETER_SRV(Texture2D<FVector4f>, MyReadOnlyTexture) // On the shader side: Texture2D<float4> MyReadOnlyTexture;

// SHADER_PARAMETER_STRUCT_REF(FMyCustomStruct, MyCustomStruct)

SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RenderTarget)

With that, you should be able to add whatever parameters you need. Here's an (untested) example with the list you provided above:

BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )

SHADER_PARAMETER_TEXTURE(Texture2D, readTex) // On the shader side: Texture2D<float4> readTex; (float4 should be whatever you expect each pixel in the texture to be, in this case float4(R,G,B,A) for 4 channels)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, writeTex) // On the shader side: RWTexture2D<float4> writeTex; (float4 should be whatever you expect each pixel in the texture to be, in this case float4(R,G,B,A) for 4 channels)
SHADER_PARAMETER(int32, range) // On the shader side: int32 range;
SHADER_PARAMETER(uint32, threshold) // On the shader side: uint32 threshold;
SHADER_PARAMETER(uint32, nstates) // On the shader side: uint32 nstates;
SHADER_PARAMETER(bool, moore) // On the shader side: bool moore;
SHADER_PARAMETER(int32, rez) // On the shader side: int32 rez;
SHADER_PARAMETER_ARRAY(FVector4f, colors, [21]) // On the shader side: float4 colors[21];

END_SHADER_PARAMETER_STRUCT()

There's also another section in the same file a little way down that sets the PassParameters:

PassParameters->range = 123;
PassParameters->moore = true;
// ...
colinbouvry commented 1 year ago

Thanks I don't understand how I put
UPROPERTY(EditAnywhere, BlueprintReadWrite) int range = 1; and link to shader to have input from the box ?

colinbouvry commented 1 year ago

I just want to link blueprint node input to uniform params on compute shader Any idea ?

AskingQuestions commented 1 year ago

There's a line in the public compute shader header file that defines this:

UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", Category = "ComputeShader", WorldContext = "WorldContextObject"))
static U...Library_AsyncExecution* ExecuteBaseMaterialComputeShader(UObject* WorldContextObject, AActor* SceneContext, UMaterialInterface* Material, ...) {

To pass a variable from BP into a uniform in your shader, you'll need to:

  1. Add an argument to that function above
  2. Add a property to the ...Library_AsyncExecution action
  3. Add a property to the F...DispatchParams struct at the top of the file
  4. Add a shader uniform to the BEGIN_SHADER_PARAMETER_STRUCT(FParameters, ) section of the main cpp file
  5. Set the shader uniform (PassParameters->...) equal to the F...DispatchParams in the dispatch part of the main cpp file.

The basemat example includes a Position parameter which you can trace through each of the steps above to get a solid understanding of how each piece moves Position from the BP call into the shader.

colinbouvry commented 1 year ago

Thanks I have not : static U...Library_AsyncExecution ExecuteBaseMaterialComputeShader(UObject WorldContextObject, AActor SceneContext, UMaterialInterface Material, ...) { I understand nothing ! Why is it too complex ?

AskingQuestions commented 1 year ago

The basemat example has a Position parameter that you can do a find/replace for in the code:

1

It starts out in the ExampleComputeShader.h file on line 101-102: We receive it as a parameter from BP

UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", Category = "ComputeShader", WorldContext = "WorldContextObject"))
static UExampleComputeShaderLibrary_AsyncExecution* ExecuteBaseMaterialComputeShader(UObject* WorldContextObject, AActor* SceneContext, UMaterialInterface* Material, FVector2D Position) {

2

We then stuff it into the Action struct on line 105

Action->Position = static_cast<FVector2f>(Position);

3

Now that we have that position field we can go over to the ExampleComputeShader.cpp file and look at how it's dispatched

The shader parameter is defined on line 55:

SHADER_PARAMETER(FVector2f, Position)

4

I just discovered that I'm not actually passing the Position param into the shader. We'll need to add that ourselves now:

Add this code just under line 139

PassParameters->OutputColor = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(OutputBuffer, PF_A32B32G32R32F));
PassParameters->Position = Params.Position; // <- Add this line here

5

Finally, this parameter is received in the ExampleComputeShader.usf file on line 4:

float2 Position;

Hopefully, this makes more sense.

Following the same pattern, you can add your own uniforms and pass them from BP.