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)
aBuffer?@computeshader, there is no way of ensuring that changes made by one taskgroup to memory is seen by another taskgroup. With@fragmentshaders, 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).