1
votes

I am trying some experiments in fractal rendering with DirectX11 Compute Shaders. The provided example runs on a FeatureLevel_10 device.

My RwStructured output buffer has a data format of R32G32B32A32_FLOAT

The problem is that when writing to the buffer, it seems that only the ALPHA ( w ) value gets written nothing else.... Here is the shader code:

struct BufType
{
    float4 value;
};

cbuffer ScreenConstants : register(b0)
{
  float2 ScreenDimensions;
  float2 Padding;
};

RWStructuredBuffer<BufType> BufferOut : register(u0);

[numthreads(1, 1, 1)]
void Main( uint3 DTid : SV_DispatchThreadID )
{
    uint index = DTid.y * ScreenDimensions.x + DTid.x;
    
    float minRe = -2.0f;
    float maxRe = 1.0f;
    float minIm = -1.2;
    float maxIm = minIm + ( maxRe - minRe ) * ScreenDimensions.y / ScreenDimensions.x;
    float reFactor = (maxRe - minRe ) / (ScreenDimensions.x - 1.0f);
    float imFactor = (maxIm - minIm ) / (ScreenDimensions.y - 1.0f);
    float cim = maxIm - DTid.y * imFactor;
    
    uint maxIterations = 30;
    
    float cre = minRe + DTid.x * reFactor;
    float zre = cre;
    float zim = cim;
    
    bool isInside = true;
    uint iterationsRun = 0;
    
    for( uint n = 0; n < maxIterations; ++n )
    {
        float zre2 = zre * zre;
        float zim2 = zim * zim;
        
        if ( zre2 + zim2 > 4.0f )
        {
            isInside = false;
            iterationsRun = n;
        }
        
        zim = 2 * zre * zim + cim;
        zre = zre2 - zim2 + cre;
    }
    
    if ( isInside )
    { 
        BufferOut[index].value = float4(1.0f,0.0f,0.0f,1.0f);
    }
}

The code actually produces in a sense the correct result ( 2D Mandelbrot set ) but it seems somehow only the alpha value is touched and nothing else is written, although the pixels inside the set should be colored red... ( the image is black & white )

Anybody has a clue what's going on here ?

5
you're only showing the HLSL code generating the buffer. What about the c code actually rendering the buffer ? How do you know for sure your buffer does not have red component ?Bahbar
Did you check the generated Asm Shader for potential compiler errors ?Stringer

5 Answers

1
votes

After some fiddling around i found the problem. I have not found any documentation from MS mentioning this, so it could also be a Nvidia specific driver issue.

Apparently you are only allowed to write ONCE per Compute Shader Invocation to the same element in a RWSructuredBuffer. And you also HAVE to write ONCE.

I changed the code to accumulate the correct color in a local variable, and write it now only once at the end of the shader.

Everything works perfectly now in that way.

0
votes

I'm not sure but, shouldn't it be for BufferOut decl:

RWStructuredBuffer<BufType> BufferOut : register(u0);

instead of :

RWStructuredBuffer BufferOut : register(u0);

If you are only using a float4 write target, why not use just:

RWBuffer<float4> BufferOut : register (u0);

Maybe this could help.

0
votes

After playing around today again, i ran into the same problem once again. The following code produced all white output:

[numthreads(1, 1, 1)]
void Main( uint3 dispatchId : SV_DispatchThreadID )
{
    float4 color = float4(1.0f,0.0f,0.0f,1.0f);
    WriteResult(dispatchId,color);
}

The WriteResult method is a utility method from my hlsl standard library.

Long story short. After i upgraded from Driver version 192 to 195(beta) the problem went away. Seems like the drivers have some definitive problems in compute shader support left, so beware.

-1
votes

from what ive seen, computer shaders are only useful if you need a more general computational model than the tradition pixel shader, or if you can load data and then share it between threads in fast shared memory. im fairly sure u would get better performance with a pixel shader for the mandelbrot shader.

on my setup (win7, feb 10 dx sdk, gtx480) my compute shaders have a punishing setup time of over 0.2-0.3ms (binding a SRV and a UAV and then calling dispatch()).

if u do a PS implementation please post your experiences.

-3
votes

I have no direct experience with DX compute shaders but...

Why are you setting alpha = 1.0?

IIRC, that makes the pixel 100% transparent, so your inside pixels are transparent red, and show up as whatever color was drawn behind them. When alpha = 1.0, the RGB components are never used.