2

I am trying to implement Photon-Mapping in DXR using DX12. Details aside, I have a RWStructured buffer that I store Photons in. The buffer is written to from within a closest hit shader, and I synchronize writes to this buffer from multiple thread groups via a counter. This works, and my photons are happily stored. I then call an instanced draw for all photons within this buffer, which rasterises their splatting radius on the screen. Theoretically, I should be able to decrement the counter within the vertex shader for this draw, and have it return to 0. However, even when I do this, the counter does not reset to 0. This means that when I move the light source per frame, the photon buffer doesn't update as it's already full from the initial frame. Any help on what I'm doing wrong would be great. :)

Note - I have tried using InterlockedAdd(countingBufferIndex, 1, dstIndex) in hlsl to synchronize access to the buffer, instead of calling dstIndex = Buffer.IncrementCounter(), however in this case, only a small number of photons are pushed to the buffer - looking at the memory in Pix, or NSight, only about 1/100th of the buffer is filled.

//create the counting buffer for the photons
void Application::CreateCountBuffer() {
    auto device = m_deviceResources->GetD3DDevice();

    UINT size = 4;
    D3D12_RESOURCE_DESC desc = {};
    desc.Alignment = 0;
    desc.DepthOrArraySize = 1;
    desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
    desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
    desc.Format = DXGI_FORMAT_UNKNOWN;
    desc.Height = 1;
    desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
    desc.MipLevels = 1;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Width = (UINT64)size;
    auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

    ThrowIfFailed(device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,  D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&photonCountBuffer)));

    photonCountBuffer->SetName(L"CountingPhotonsBuffer");
    photonCounterDescriptorHeapIndex = AllocateDescriptor(&photonCountCPUDescriptor, photonCounterDescriptorHeapIndex);

    D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
    uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
    uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
    uavDesc.Buffer.NumElements = 1;
    uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;

    device->CreateUnorderedAccessView(photonCountBuffer.Get(), nullptr, &uavDesc, photonCountCPUDescriptor);
    photonCounterGpuDescriptor = CD3DX12_GPU_DESCRIPTOR_HANDLE(m_descriptorHeap->GetGPUDescriptorHandleForHeapStart(), photonCountUavDescriptorHeapIndex, m_descriptorSize);
}

//create the RWStructuredBuffer for storing the photons
void Application::CreatePhotonStructuredBuffer() {
    
    auto device = m_deviceResources->GetD3DDevice();
    auto backBufferFormat = m_deviceResources->GetBackBufferFormat();
    {
        UINT64 size = sizeof(Photon);
        UINT64 bufferSize = PHOTON_COUNT * size;
        auto uavDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
        auto defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

        ThrowIfFailed(device->CreateCommittedResource(&defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &uavDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&photonStructBuffer)));
        NAME_D3D12_OBJECT(photonStructBuffer);

        photonStructGpuHeapIndex = AllocateDescriptor(&photonStructCPUDescriptor, photonStructGpuHeapIndex);
        D3D12_UNORDERED_ACCESS_VIEW_DESC uavPhotonDesc = {};
        uavPhotonDesc.Buffer.NumElements = PHOTON_COUNT;
        uavPhotonDesc.Buffer.FirstElement = 0;
        uavPhotonDesc.Buffer.StructureByteStride = size;
        uavPhotonDesc.Buffer.CounterOffsetInBytes = 0;
        uavPhotonDesc.Format = DXGI_FORMAT_UNKNOWN;
        uavPhotonDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
        device->CreateUnorderedAccessView(photonStructBuffer.Get(),photonCountBuffer.Get(), &uavPhotonDesc, photonStructCPUDescriptor);
        photonStructGPUDescriptor = CD3DX12_GPU_DESCRIPTOR_HANDLE(m_descriptorHeap->GetGPUDescriptorHandleForHeapStart(), photonStructGpuHeapIndex, m_descriptorSize);
    }
}

///////////Registers for Photon Structured Buffer and counter buffer within Ray-Tracing shader/////////////
RWStructuredBuffer<Photon> photonBuffer : register(u1);
RWByteAddressBuffer photonBufferCounter : register(u2);
////////////Storing Photons - called within a Closest Hit shader/////////////////


        uint dstIndex = photonBuffer.IncrementCounter();
        float raySize = sqrt(dot(pos - WorldRayOrigin(), pos - WorldRayOrigin()));
        Photon p = { float4(pos, raySize), float4(dir, 1), float4(colour, 1), float4(attr.normal, 1) };
        
        if (dstIndex < PHOTON_COUNT) {
            photonBuffer[dstIndex] = p;
        }
        else {
           uint decr = photonBuffer.DecrementCounter();
            }
        }
        

/////////////Register for Photon Buffer within Raster Pipeline //////////////////////////////////////////////////////////////////////
RWStructuredBuffer<Photon> photons : register(u1);
//////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////
///////////Decrement Counter - called within the vertex shader of an instanced draw (called per photon)//////
/////////////////////////////////////////////////////////////////////////////////////////////////////

PSInput VSMain(float4 position : POSITION, uint instanceID : SV_InstanceID, float4 color : COLOR)
{
    float lMax = 50;
    float maxMajorKernelRadius = 10;
    float minMajKernelRadius = 0.1;
    float pi = 3.1415926535897932384626422832795028841971f;

    PSInput result;
    Photon photon = photons[instanceID];
    uint decr = photons.DecrementCounter();
    .
    .
    .
    }

0 Answers0