| 75 | } |
| 76 | |
| 77 | void PrefixSum::execute( |
| 78 | RenderContext* pRenderContext, |
| 79 | ref<Buffer> pData, |
| 80 | uint32_t elementCount, |
| 81 | uint32_t* pTotalSum, |
| 82 | ref<Buffer> pTotalSumBuffer, |
| 83 | uint64_t pTotalSumOffset |
| 84 | ) |
| 85 | { |
| 86 | FALCOR_PROFILE(pRenderContext, "PrefixSum::execute"); |
| 87 | |
| 88 | FALCOR_ASSERT(pRenderContext); |
| 89 | FALCOR_ASSERT(elementCount > 0); |
| 90 | FALCOR_ASSERT(pData && pData->getSize() >= elementCount * sizeof(uint32_t)); |
| 91 | |
| 92 | // Clear total sum to zero. |
| 93 | pRenderContext->clearUAV(mpTotalSum->getUAV().get(), uint4(0)); |
| 94 | |
| 95 | uint32_t maxElementCountPerIteration = kGroupSize * kGroupSize * 2; |
| 96 | uint32_t totalElementCount = elementCount; |
| 97 | uint32_t iterationsCount = div_round_up(totalElementCount, maxElementCountPerIteration); |
| 98 | |
| 99 | for (uint32_t iter = 0; iter < iterationsCount; iter++) |
| 100 | { |
| 101 | // Compute number of thread groups in the first pass. Each thread operates on two elements. |
| 102 | uint32_t numPrefixGroups = std::max(1u, div_round_up(std::min(elementCount, maxElementCountPerIteration), kGroupSize * 2)); |
| 103 | FALCOR_ASSERT(numPrefixGroups > 0 && numPrefixGroups <= kGroupSize); |
| 104 | |
| 105 | // Copy previus iterations total sum to read buffer. |
| 106 | pRenderContext->copyResource(mpPrevTotalSum.get(), mpTotalSum.get()); |
| 107 | |
| 108 | // Pass 1: compute per-thread group prefix sums. |
| 109 | { |
| 110 | // Clear group sums to zero. |
| 111 | pRenderContext->clearUAV(mpPrefixGroupSums->getUAV().get(), uint4(0)); |
| 112 | |
| 113 | // Set constants and data. |
| 114 | auto var = mpPrefixSumGroupVars->getRootVar(); |
| 115 | var["CB"]["gNumGroups"] = numPrefixGroups; |
| 116 | var["CB"]["gTotalNumElems"] = totalElementCount; |
| 117 | var["CB"]["gIter"] = iter; |
| 118 | var["gData"] = pData; |
| 119 | |
| 120 | mpComputeState->setProgram(mpPrefixSumGroupProgram); |
| 121 | pRenderContext->dispatch(mpComputeState.get(), mpPrefixSumGroupVars.get(), {numPrefixGroups, 1, 1}); |
| 122 | } |
| 123 | |
| 124 | // Add UAV barriers for our buffers to make sure writes from the previous pass finish before the next pass. |
| 125 | // This is necessary since the buffers are bound as UAVs in both passes and there are no resource transitions. |
| 126 | pRenderContext->uavBarrier(pData.get()); |
| 127 | pRenderContext->uavBarrier(mpPrefixGroupSums.get()); |
| 128 | |
| 129 | // Pass 2: finalize prefix sum by adding the sums to the left to each group. |
| 130 | // This is only necessary if we have more than one group. |
| 131 | if (numPrefixGroups > 1) |
| 132 | { |
| 133 | // Compute number of thread groups. Each thread operates on one element. |
| 134 | // Note that we're skipping the first group of 2N elements, as no add is needed (their group sum is zero). |
no test coverage detected