S
S
SpecterSpect2020-07-19 12:03:16
C++ / C#
SpecterSpect, 2020-07-19 12:03:16

How to optimize writing to RWStructuredBuffer?

I want to transfer my path tracer from a pixel shader to several compute shaders, so that firstly it would be more convenient to set the scene, and secondly, to avoid a problem with textures (the number of slots for textures is limited. I want to determine when a ray collides with an object, with which one the object it collided with, and in accordance with the texture specified in the object, set the color of the surface that the ray collided with). But the problem is that my idea turns out to be very unoptimized, the fps drops to 30 when drawing 2 spheres (when calculating the path tracing with two spheres in one shader, the fps was about 700). Here is a sample code:
```
struct Ray
{
float3 direction;
floatt;
float3 origin;
float padding1;
float3 energy;
float padding2;
float3result;
float padding3;
};

RWTexture2D Result : register(u0);
RWStructuredBuffer tray : register(u1);

Ray InitRay0(float3 direction, float3 origin)
{
Ray ray;
ray.t = 0;
ray direction = direction;
ray.origin = origin;
ray energy = 1;
ray.result = 0;
ray padding1 = 0;
ray padding2 = 0;
ray padding3 = 0;
return ray;
}

[numthreads(8, 8, 1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
_seed = _randValue;
uint-width, height;
Result.GetDimensions(width, height);
uint oneDID = threadID.x + threadID.y * width;
for (int i = 0; i < 8; i++)
{
tray[oneDID] = InitRay0(float3(0, 0, 0), float3(0, 0, 0));
Result[threadID.xy] = float4(tray[oneDID].result, 1);
}
}
```
I want to transfer my path tracer from a pixel shader to several compute shaders, so that firstly it would be more convenient to set the scene, and secondly, to avoid a problem with textures (the number of slots for textures is limited. I want to determine when a ray collides with an object, with which one the object it collided with, and in accordance with the texture specified in the object, set the color of the surface that the ray collided with). But the problem is that my idea turns out to be very unoptimized, the fps drops to 30 when drawing 2 spheres (when calculating the path tracing with two spheres in one shader, the fps was about 700). Here is a sample code:

struct Ray
{
float3 direction;
floatt;
float3 origin;
float padding1;
float3 energy;
float padding2;
float3result;
float padding3;
};

RWTexture2D Result : register(u0);
RWStructuredBuffer tray : register(u1);

Ray InitRay0(float3 direction, float3 origin)
{
Ray ray;
ray.t = 0;
ray direction = direction;
ray.origin = origin;
ray energy = 1;
ray.result = 0;
ray padding1 = 0;
ray padding2 = 0;
ray padding3 = 0;
return ray;
}

[numthreads(8, 8, 1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
_seed = _randValue;
uint-width, height;
Result.GetDimensions(width, height);
uint oneDID = threadID.x + threadID.y * width;
for (int i = 0; i < 8; i++)
{
tray[oneDID] = InitRay0(float3(0, 0, 0), float3(0, 0, 0));
Result[threadID.xy] = float4(tray[oneDID].result, 1);
}
}
Yes, this is not path tracing, I just emulate the load with this code. In this case, instead of a cycle, there should be several shader calls, with different data binding. At the same time, the fps is about 60 (but in that example with real tracing it was 30, the important thing is that overwriting data into the buffer is very loading, apparently). Maybe I somehow do not properly distribute the flows, or did not properly pack the structures? Well, or my idea is not very optimized and you need to find another approach, but what? What's the problem? (Yes, it's probably not correct to measure FPS, but these are approximate data, the point is that FPS is clearly becoming very small, even visible to the naked eye)

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question