问题描述
我正在尝试使用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 (将#修改为@)