Closed Zifkan closed 11 months ago
Here's a quick (untested) write-up from a project I did a little while ago. Hopefully, this will help point you in the right direction:
The following assumes you already have:
You can create a "UserData" struct for the VertexFactory like this (if you haven't already done so):
// VertexFactory.h
/**
* Per frame UserData to pass to the vertex shader.
*/
struct FMyFactoryUserData : public FOneFrameResource
{
FRHIShaderResourceView* DataFromComputeShaderSRV;
};
Inside of GetElementShaderBindings()
in your VertexFactory:
// VertexFactory.cpp
GetElementShaderBindings(...) {
...
FMyFactoryUserData * UserData = (FMyFactoryUserData *)BatchElement.UserData;
ShaderBindings.Add(InstanceBufferParameter, UserData->DataFromComputeShaderSRV);
...
}
Inside of GetDynamicMeshElements
in your scene proxy within the batch element loop:
FMyFactoryUserData *UserData = &Collector.AllocateOneFrameResource<FMyFactoryUserData>();
BatchElement.UserData = (void *)UserData;
UserData->DataFromComputeShaderSRV = /* Grab the FShaderResourceViewRHIRef from your state somewhere */;
You'll need to transition the buffer(s) from UAVMask
to SRVMask
after you're done dispatching compute shaders that write to the resource for this frame:
// Transition from SRVMask to UAVMask
TArray<FRHITransitionInfo> TransitionInfos;
TransitionInfos.Add(FRHITransitionInfo(DataFromComputeShaderBufferUAV, ERHIAccess::SRVMask,ERHIAccess::UAVMask ));
// Transition from UAVMask to SRVMask
TArray<FRHITransitionInfo> TransitionInfos;
TransitionInfos.Add(FRHITransitionInfo(DataFromComputeShaderBufferUAV, ERHIAccess::UAVMask ,ERHIAccess::SRVMask));
// Dispatch the transition
AddPass(GraphBuilder, RDG_EVENT_NAME("TransitionDrawBuffer"), [TransitionInfos](FRHICommandList &InRHICmdList) {
InRHICmdList.Transition(TransitionInfos);
});
You can dispatch multiple compute shaders one after the other who all write to an arbitrary buffer. After you're done writing to them you can use the transition code above to transition the buffer(s) for drawing. Once you're done drawing (start of next frame) you can transition them back to writable.
So the high-level overview of the steps that run each frame look like this: Start of frame
@AskingQuestions tyvm for answer. Anyway i can't understand how to assign buffer between shaders and factory. UAV buffer created through GraphBuilder.CreateUAV returning FRDGBufferUAVRef. So this type should be convert or remade somehow to FShaderResourceViewRHIRef (for me my factory beffers made as this type )SRV type for factory?
Good question, I forgot to mention this:
You're going to have to create the buffer outside of the RDG.
You can make a FBufferRHIRef
by doing:
FRHIResourceCreateInfo CreateInfo(TEXT("helpful name"));
FBufferRHIRef YourBuffer = RHICreateStructuredBuffer(ItemSize, BufferSize, BUF_UnorderedAccess | BUF_ShaderResource, ERHIAccess::SRVMask, CreateInfo);
YourBufferUAV = RHICreateUnorderedAccessView(YourBuffer, false, false);
YourBufferSRV = RHICreateShaderResourceView(YourBuffer);
You'll also have to change your shader parameter from RDG to non-RDG in the compute shader definition:
SHADER_PARAMETER_UAV(RWStructuredBuffer<...>, RWYourBuffer)
When assigning PassParameters:
PassParameters->RWYourBuffer = YourBufferUAV;
When assigning UserData for the vertex factory:
UserData->YourBufferSRV = YourBufferSRV;
I need some help. I have two Compute Shaders and one Vertex shader with custom vertex factory.
1) I want buffer SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, Output) for shader1 pass it into shader2 without reading it on CPU. I thought about made "shared" buffer. But i don't know what type to choose. Shader one will write into eat and Shader2 will read it.
So lets say that how i use this buffer in Shader1 reading it on CPU
So how should i change it to pass it into shader2 without CPU reading.
2) Later i want that shader2 when done his job also pass another "shared" buffer into Vertex Shader (Vertex factory). So it should be also something like this, but as in first example im not really sure how to properly define it.
in my custom CustomLocalVertexFactory.ush i declare it like this Buffer Instancing_BoneMatrixBufferSRV;
In Vertex factory bind like this
and then using memcopy through
FShaderResourceViewRHIRef MatrixBufferSRV;
but want avoid this and pass from shader2 into Vertex Factory directly