RWStructuredBuffer计数器不减量DX12

问题描述

我正在尝试使用DX12在DXR中实现光子映射。除了细节之外,我还有一个RWStructured缓冲区,用于存储光子。该缓冲区是从最近的命中着色器中写入的,并且我通过一个计数器从多个线程组同步对该缓冲区的写入。这有效,并且我的光子被愉快地存储了。然后,我为该缓冲区中的所有光子调用实例化绘图,这会将它们在屏幕上的辐射半径光栅化。从理论上讲,我应该能够在此绘制的顶点着色器中递减计数器,并使计数器返回0。但是,即使执行此操作,计数器也不会重置为0。这意味着当我移动光源时每帧,光子缓冲区不会更新,因为从初始帧开始它已经满了。任何对我做错事的帮助都会很棒。 :)

注意-我尝试使用hlsl中的InterlockedAdd(countingBufferIndex,1,dstIndex)来同步对缓冲区的访问,而不是调用dstIndex = Buffer.IncrementCounter(),但是在这种情况下,仅推送了少量光子到缓冲区-查看Pix或NSight中的内存,仅占缓冲区的大约1/100。

//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(),&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,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,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();
    .
    .
    .
    }

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)