Jump to content
  • Advertisement
Sign in to follow this  
Happy SDE

Elegant reduction algorithm on CS

This topic is 615 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Forum!

I need to reduce 2D texture.
For each Dispatch(), I reduce it 16x both directions on CS.
The biggest problem arises when I have the last step, say when texture is 8x5. For previous steps it is not such big.

I found next solution: store in CB for the last, not complete quads, their real denominators, and use it instead of division by 16*16.
CB data is changed on Resize() only, so I don’t need to update it every frame: I just store vector of them as reduction targets.

But I wonder: is there more elegant solution?

Here is a scratch:

static const uint gLumReductionTGSize = 16;

cbuffer CB
{
    uint cb_xGroupId;
    uint cb_xDenominator; //if GroupID.x == cb_xGroupId, use it. Otherwise - gLumReductionTGSize  
    uint cb_yGroupId;
    uint cb_yDenominator; //if GroupID.y == cb_yGroupId, use it. Otherwise - gLumReductionTGSize  
}


//Each time reduce by 16x16
[numthreads(gLumReductionTGSize, gLumReductionTGSize, 1)]
void main(uint3 GroupID : SV_GroupID, uint3 DispatchThreadId : SV_DispatchThreadID, uint ThreadIndex : SV_GroupIndex)
{
    // Will read 0 in case "out of bounds"
    float pixelLuminance = InputLumMap[DispatchThreadId.xy];

    // Store in shared memory
    LumSamples[ThreadIndex] = pixelLuminance;
    GroupMemoryBarrierWithGroupSync();

    // Reduce
    [unroll]
    for (uint s = NumThreads / 2; s > 0; s >>= 1)
    {
        if (ThreadIndex < s)
        {
            LumSamples[ThreadIndex] += LumSamples[ThreadIndex + s];
        }

        GroupMemoryBarrierWithGroupSync();
    }

    if (ThreadIndex == 0)
    {
        uint divX = (GroupID.x == cb_xGroupId) ? cb_xDenominator : gLumReductionTGSize;
        uint divY = (GroupID.y == cb_yGroupId) ? cb_yDenominator : gLumReductionTGSize;

        OutputLumMap[GroupID.xy] = LumSamples[0] / (divX* divY);
    }
}

Thanks in advance!

Edited by Happy SDE

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!