所以,我真正想要的在理论上相当简单,但我无法让它在实践中发挥作用。
我只是想从(光线跟踪)着色器读取和写入动态大小的浮点数组。我认为正确的做法是将这个阵列声明为无人机。
但是,我尝试将其声明为
RWTexture1D<float>
以及 RWBuffer<float>
。但对于两者,我都收到尺寸太大的错误。我指定的尺寸约为 100k,但似乎 RWBuffer<float>
仅限于 25k,RWTexture1D<float>
仅限于 16384。我该怎么办?
编辑:这是代码:
D3D12_UNORDERED_ACCESS_VIEW_DESC unordered_access_view_desc{};
unordered_access_view_desc.Buffer.NumElements = 100000;
unordered_access_view_desc.Format = DXGI_FORMAT_R32_FLOAT;
unordered_access_view_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
d3d.device->CreateUnorderedAccessView(resource, nullptr, &unordered_access_view_desc, handle);
和错误:
至少由于以下条件之一,视图的尺寸无效。假设此格式(0x29,R32_FLOAT),FirstElement(值 = 0)必须介于 0 和缓冲区的最大偏移量 24999(含)之间。
我不明白这个。如果格式是
DXGI_FORMAT_R32G32B32A32_FLOAT
而我会选择 Buffer.NumElements = 25000
我最终会分配相同数量的内存。
但是即使我使用这个 hack,真的不可能创建一个大小 > 25000 的一维数组吗?即使是大小为 512x512 的简单二维纹理也具有更多值 (262144)。我真的需要创建这样的二维纹理并适当地重新索引吗?
为了使用更多元素,需要使用 StructuredBuffers, 所以在你的 hlsl 代码中你需要使用
RWStructuredBuffer<float>
设置视图的代码也不同,需要设置为:
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = ElementCount; // number of elements you need in your buffer
uavDesc.Buffer.StructureByteStride = sizeof(float); //size of one element
uavDesc.Buffer.CounterOffsetInBytes = 0;
uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
要创建资源,您可以继续使用 CreateCommissedResource:
D3D12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(elementCount * elmentSize , D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
支持大缓冲区的另一种方法是原始缓冲区。
它们作为 RWByteAddressBuffer(读+写访问)或 ByteAddressBuffer(只读访问)对象向 HLSL 公开。请注意,在着色器中加载/存储数据时,您将需要字节偏移量而不是元素偏移量(即将元素偏移量乘以 4)和
asfloat
/ asuint
。
您需要在创建视图时指定
DXGI_FORMAT_R32_TYPELESS
作为缓冲区的格式,并指定 D3D12_BUFFER_UAV_FLAG_RAW
或 D3D12_BUFFER_SRV_FLAG_RAW
标志。