0

I am getting errors when using a variable that is dependent on the value of a texture sample in the critical section of my fragment shader.

From what I understand, one should not sample textures in the critical section of the code because of diverging paths. As a result, I moved the initialization of fragData to the beginning so getPBRColor() is outside of the critical section. But I think that because fragData is still dependent on color when I use it in the critical section it still suffers from the error. Is there no way to use the value of a sampled texture inside the critical section?

Edit: Ignore the actual usage of the aBuffer. The important part is that I cannot write the color into it.

struct FragData {
    color: vec4<f32>,
    depth: f32,
}

@group(0) @binding(0) var baseColorTexture: texture_2d<f32>;
@group(0) @binding(1) var baseColorSampler: sampler;

// Accumulation buffer that I want to write a fragment's color and depth to
@group(1) @binding(0) var<storage, read_write> aBuffer: array<FragData>;

// A lock for each pixel. Has byte size = resolution.x * resolution.y * sizeOf(u32)
@group(1) @binding(1) var<storage, read_write> spinLock: array<atomic<u32>>;

@fragment
fn_main(input: FragmentInput) {
    let color: vec4<f32> = getPBRColor(input) // samples baseColorTexture to get color
    let fragDepth = input.position.z;
    let fragData = FragData(color, fragDepth); // causes crash
    //let fragData = FragData(vec4(0.0f), fragDepth); // runs fine

    let pixelIndex = input.position.y * resolution.x + input.position.x

    var keepWaiting = true;
    while (keepWaiting) {
        // CRITICAL SECTION: Attempt to acquire the lock
        if (atomicCompareExchangeWeak(&spinLock[pixelIndex], 0u, 1u).exchanged) {
            // This will cause the error depending if fragData.color uses a sampled value or not
            aBuffer[pixelIndex] = fragData;
        
            // Release the lock
            atomicStore(&spinLock[pixelIndex], 0u);
            keepWaiting = false;
        }
    }
}

Resulting error: GLDRendererMetal command buffer completion error: Error Domain=MTLCommandBufferErrorDomain Code=1 "Discarded (victim of GPU error/recovery) (00000005:kIOGPUCommandBufferCallbackErrorInnocentVictim)" UserInfo={NSLocalizedDescription=Discarded (victim of GPU error/recovery) (00000005:kIOGPUCommandBufferCallbackErrorInnocentVictim)

3
  • 1
    Not that it matters, but why are you using a spin lock? Isn't each instance of fn_main writing to a different index in aBuffer? Commented Apr 10 at 22:25
  • I am trying to implement spinlock order independent transparency Commented Apr 10 at 22:44
  • I seriously doubt that you're going to get this to work on Metal. When using a @compute shader, there is no way of ensuring that changes made by one taskgroup to memory is seen by another taskgroup. With @fragment shaders, the situation is even worse because you have no control over task groups and you cannot use the memory synchronization primitives (which are only for @compute). Commented Apr 16 at 19:53

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.