Skip to content

Commit 07172eb

Browse files
committed
fixed fragshaderinterlock programmable blending critical bug
1 parent 8514d3b commit 07172eb

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

62_CAD/shaders/main_pipeline/fragment_shader.hlsl

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,13 @@ typedef StyleClipper< nbl::hlsl::shapes::Line<float> > LineStyleClipper;
340340
// textureColor: color sampled from a texture
341341
// useStyleColor: instead of writing and reading from colorStorage, use main object Idx to find the style color for the object.
342342
template<bool FragmentShaderPixelInterlock>
343-
float32_t4 calculateFinalColor(const uint2 fragCoord, const float localAlpha, const uint32_t currentMainObjectIdx, float3 textureColor);
343+
float32_t4 calculateFinalColor(const uint2 fragCoord, const float localAlpha, const uint32_t currentMainObjectIdx, float3 textureColor, bool colorFromTexture);
344344

345345
template<>
346-
float32_t4 calculateFinalColor<false>(const uint2 fragCoord, const float localAlpha, const uint32_t currentMainObjectIdx, float3 localTextureColor)
346+
float32_t4 calculateFinalColor<false>(const uint2 fragCoord, const float localAlpha, const uint32_t currentMainObjectIdx, float3 localTextureColor, bool colorFromTexture)
347347
{
348348
uint32_t styleIdx = mainObjects[currentMainObjectIdx].styleIdx;
349-
const bool colorFromStyle = styleIdx != InvalidStyleIdx;
350-
if (colorFromStyle)
349+
if (!colorFromTexture)
351350
{
352351
float32_t4 col = lineStyles[styleIdx].color;
353352
col.w *= localAlpha;
@@ -357,10 +356,10 @@ float32_t4 calculateFinalColor<false>(const uint2 fragCoord, const float localAl
357356
return float4(localTextureColor, localAlpha);
358357
}
359358
template<>
360-
float32_t4 calculateFinalColor<true>(const uint2 fragCoord, const float localAlpha, const uint32_t currentMainObjectIdx, float3 localTextureColor)
359+
float32_t4 calculateFinalColor<true>(const uint2 fragCoord, const float localAlpha, const uint32_t currentMainObjectIdx, float3 localTextureColor, bool colorFromTexture)
361360
{
362361
float32_t4 color;
363-
362+
364363
nbl::hlsl::spirv::execution_mode::PixelInterlockOrderedEXT();
365364
nbl::hlsl::spirv::beginInvocationInterlockEXT();
366365

@@ -370,21 +369,26 @@ float32_t4 calculateFinalColor<true>(const uint2 fragCoord, const float localAlp
370369
const uint32_t storedQuantizedAlpha = nbl::hlsl::glsl::bitfieldExtract<uint32_t>(packedData,0,AlphaBits);
371370
const uint32_t storedMainObjectIdx = nbl::hlsl::glsl::bitfieldExtract<uint32_t>(packedData,AlphaBits,MainObjectIdxBits);
372371
// if geomID has changed, we resolve the SDF alpha (draw using blend), else accumulate
373-
const bool resolve = currentMainObjectIdx != storedMainObjectIdx;
374-
uint32_t resolveStyleIdx = mainObjects[storedMainObjectIdx].styleIdx;
375-
376-
// TODO[Przemek]: REMOVE when READ --> if linestyle value in mainObject is invalid then we're using localTextureColor instead of the linestyle color, this should be true for DTM meshes to resolve color with what's stored in colorStorage and not from the lineStyle color
377-
const bool resolveColorFromStyle = resolveStyleIdx != InvalidStyleIdx;
372+
const bool differentMainObject = currentMainObjectIdx != storedMainObjectIdx; // meaning current pixel's main object is different than what is already stored
373+
const bool resolve = differentMainObject && storedMainObjectIdx != InvalidMainObjectIdx;
374+
uint32_t toResolveStyleIdx = InvalidStyleIdx;
378375

379376
// load from colorStorage only if we want to resolve color from texture instead of style
380377
// sampling from colorStorage needs to happen in critical section because another fragment may also want to store into it at the same time + need to happen before store
381-
if (resolve && !resolveColorFromStyle)
382-
color = float32_t4(unpackR11G11B10_UNORM(colorStorage[fragCoord]), 1.0f);
383-
384-
if (resolve || localQuantizedAlpha > storedQuantizedAlpha)
378+
if (resolve)
379+
{
380+
toResolveStyleIdx = mainObjects[storedMainObjectIdx].styleIdx;
381+
if (toResolveStyleIdx == InvalidStyleIdx) // if style idx to resolve is invalid, then it means we should resolve from color
382+
color = float32_t4(unpackR11G11B10_UNORM(colorStorage[fragCoord]), 1.0f);
383+
}
384+
385+
// If current localAlpha is higher than what is already stored in pseudoStencil we will update the value in pseudoStencil or the color in colorStorage, this is equivalent to programmable blending MAX operation.
386+
// OR If previous pixel has a different ID than current's (i.e. previous either empty/invalid or a differnet mainObject), we should update our alpha and color storages.
387+
if (differentMainObject || localQuantizedAlpha > storedQuantizedAlpha)
385388
{
386389
pseudoStencil[fragCoord] = nbl::hlsl::glsl::bitfieldInsert<uint32_t>(localQuantizedAlpha,currentMainObjectIdx,AlphaBits,MainObjectIdxBits);
387-
colorStorage[fragCoord] = packR11G11B10_UNORM(localTextureColor);
390+
if (colorFromTexture) // writing color from texture
391+
colorStorage[fragCoord] = packR11G11B10_UNORM(localTextureColor);
388392
}
389393

390394
nbl::hlsl::spirv::endInvocationInterlockEXT();
@@ -394,8 +398,8 @@ float32_t4 calculateFinalColor<true>(const uint2 fragCoord, const float localAlp
394398

395399
// draw with previous geometry's style's color or stored in texture buffer :kek:
396400
// we don't need to load the style's color in critical section because we've already retrieved the style index from the stored main obj
397-
if (resolveColorFromStyle)
398-
color = lineStyles[resolveStyleIdx].color;
401+
if (toResolveStyleIdx != InvalidStyleIdx) // if toResolveStyleIdx is valid then that means our resolved color should come from line style
402+
color = lineStyles[toResolveStyleIdx].color;
399403
color.a *= float(storedQuantizedAlpha) / 255.f;
400404

401405
return color;
@@ -407,7 +411,6 @@ float4 main(PSInput input) : SV_TARGET
407411
float localAlpha = 0.0f;
408412
float3 textureColor = float3(0, 0, 0); // color sampled from a texture
409413

410-
411414
// TODO[Przemek]: Disable All the object rendering paths if you want.
412415
ObjectType objType = input.getObjType();
413416
const uint32_t currentMainObjectIdx = input.getMainObjectIdx();
@@ -646,9 +649,10 @@ float4 main(PSInput input) : SV_TARGET
646649
if (localAlpha <= 0)
647650
discard;
648651

652+
const bool colorFromTexture = objType == ObjectType::IMAGE;
649653

650654
// TODO[Przemek]: But make sure you're still calling this, correctly calculating alpha and texture color.
651655
// you can add 1 main object and push via DrawResourcesFiller like we already do for other objects (this go in the mainObjects StorageBuffer) and then set the currentMainObjectIdx to 0 here
652656
// having 1 main object temporarily means that all triangle meshes will be treated as a unified object in blending operations.
653-
return calculateFinalColor<nbl::hlsl::jit::device_capabilities::fragmentShaderPixelInterlock>(fragCoord, localAlpha, currentMainObjectIdx, textureColor);
657+
return calculateFinalColor<nbl::hlsl::jit::device_capabilities::fragmentShaderPixelInterlock>(fragCoord, localAlpha, currentMainObjectIdx, textureColor, colorFromTexture);
654658
}

62_CAD/shaders/main_pipeline/resolve_alphas.hlsl

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,29 @@ float32_t4 calculateFinalColor<true>(const uint2 fragCoord)
2626
const uint32_t storedQuantizedAlpha = nbl::hlsl::glsl::bitfieldExtract<uint32_t>(packedData,0,AlphaBits);
2727
const uint32_t storedMainObjectIdx = nbl::hlsl::glsl::bitfieldExtract<uint32_t>(packedData,AlphaBits,MainObjectIdxBits);
2828
pseudoStencil[fragCoord] = nbl::hlsl::glsl::bitfieldInsert<uint32_t>(0, InvalidMainObjectIdx, AlphaBits, MainObjectIdxBits);
29+
30+
// if geomID has changed, we resolve the SDF alpha (draw using blend), else accumulate
31+
const bool resolve = storedMainObjectIdx != InvalidMainObjectIdx;
32+
uint32_t toResolveStyleIdx = InvalidStyleIdx;
2933

30-
uint32_t resolveStyleIdx = mainObjects[storedMainObjectIdx].styleIdx;
31-
const bool resolveColorFromStyle = resolveStyleIdx != InvalidStyleIdx;
32-
if (!resolveColorFromStyle)
33-
color = float32_t4(unpackR11G11B10_UNORM(colorStorage[fragCoord]), 1.0f);
34+
// load from colorStorage only if we want to resolve color from texture instead of style
35+
// sampling from colorStorage needs to happen in critical section because another fragment may also want to store into it at the same time + need to happen before store
36+
if (resolve)
37+
{
38+
toResolveStyleIdx = mainObjects[storedMainObjectIdx].styleIdx;
39+
if (toResolveStyleIdx == InvalidStyleIdx) // if style idx to resolve is invalid, then it means we should resolve from color
40+
color = float32_t4(unpackR11G11B10_UNORM(colorStorage[fragCoord]), 1.0f);
41+
}
3442

3543
nbl::hlsl::spirv::endInvocationInterlockEXT();
3644

37-
if (resolveColorFromStyle)
38-
color = lineStyles[resolveStyleIdx].color;
45+
if (!resolve)
46+
discard;
47+
48+
// draw with previous geometry's style's color or stored in texture buffer :kek:
49+
// we don't need to load the style's color in critical section because we've already retrieved the style index from the stored main obj
50+
if (toResolveStyleIdx != InvalidStyleIdx) // if toResolveStyleIdx is valid then that means our resolved color should come from line style
51+
color = lineStyles[toResolveStyleIdx].color;
3952
color.a *= float(storedQuantizedAlpha) / 255.f;
4053

4154
return color;

0 commit comments

Comments
 (0)