在分派我的着色器之前,我如何写入我的 ID3D11UnorderedAccessView 的缓冲区?
How can I write to my ID3D11UnorderedAccessView's buffer before dispatching my shader?
假设我有
ID3D11UnorderedAccessView* pDataView
我有
byte* pRawData
如何使用 pRawData 设置 pDataView 的缓冲区?
注意:FAILED 和 CHR 是错误检查宏。
更新:当我创建无人机时,Soonts 给出了一个似乎可以解决问题的答案,但为了完整性,我还希望能够从 CPU 在两者都被创建之后。我没有那么成功地尝试过。如果我有:
template <typename T>
static inline void CreateUnorderedAccessViewFromFile(
_In_ ID3D11Device* pDevice,
_In_ ID3D11DeviceContext* pDeviceContext,
_In_ HANDLE dataFile,
_Out_ ID3D11Buffer** ppBuffer,
_Out_ ID3D11UnorderedAccessView** ppUav)
{
uint64_t fileSize;
//CBR(::GetFileSizeEx(handle, &fileSize));
//Custom size for testing purposes
fileSize = 0x800;
D3D11_BUFFER_DESC bufferDesc =
{
fileSize, // ByteWidth
D3D11_USAGE_DEFAULT, // Usage
D3D11_BIND_UNORDERED_ACCESS, // BindFlags
D3D11_CPU_ACCESS_WRITE, // CPUAccessFlags
D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, // MiscFlags
sizeof(T), // StructureByteStride
};
CHR(pDevice->CreateBuffer(
&bufferDesc,
nullptr,
ppBuffer));
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = pDeviceContext->Map(
*ppBuffer,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&mappedResource);
byte* ppData = reinterpret_cast<byte*>(mappedResource.pData);
for (uint64_t i = 0; i < fileSize; i += 0x10000)
{
DWORD readSize = min(fileSize - i, 0x10000);
if (!ReadFile(
dataFile,
ppData,
readSize,
NULL,
NULL))
{
uint32_t lastError = ::GetLastError();
CBR(lastError != ERROR_IO_PENDING);
}
}
pDeviceContext->Unmap(
*ppBuffer,
0);
D3D11_UNORDERED_ACCESS_VIEW_DESC uaView =
{
DXGI_FORMAT_UNKNOWN, // Format
D3D11_UAV_DIMENSION_BUFFER, // ViewDimension
};
uaView.Buffer.FirstElement = 0;
uaView.Buffer.Flags = 0;
uaView.Buffer.NumElements = fileSize / sizeof(T);
CHR(pDevice->CreateUnorderedAccessView(
*ppBuffer,
&uaView,
ppUav));
}
为什么我会 E_INVALIDARG 在地图上?
注意:FAILED 和 CHR 是错误检查宏。
首先您需要为您的数据创建一个缓冲区。
如果您的数据是 2D 纹理,请调用 ID3D11Device::CreateTexture2D。不要忘记 D3D11_TEXTURE2D_DESC::BindFlags 字段中的 D3D11_BIND_UNORDERED_ACCESS。您可以在 D3D11_SUBRESOURCE_DATA 结构中的第二个参数中传递 byte* pRawData
。
如果您的数据是一维结构数组,请调用 ID3D11Device::CreateBuffer,您应该再次传递 D3D11_BIND_UNORDERED_ACCESS 和您的初始数据。
无人机还支持其他类型的资源:1D 纹理、1D 纹理数组、2D 纹理数组、3D 纹理。这完全取决于您的数据,以及处理该数据的着色器。
最后,调用 ID3D11Device::CreateUnorderedAccessView 传递 ID3D11Texture2D、ID3D11Buffer 或其他一些资源。 ID3D11Texture2D、ID3D11Buffer等都是继承自ID3D11Resource,所以你可以传其中一个。
更新: 如果您已经创建了两者并且您只需要更新,请在您的 pDataView 上调用 GetResource 以从视图中获取资源。然后更新缓冲区 ID3D11DeviceContext::Map、memcpy、ID3D11DeviceContext::Unmap。只要确保您已经创建了允许这样做的资源,即 D3D11_CPU_ACCESS_WRITE.
更新: 正如评论者所说,您不能直接从 CPU 更新无人机资源。解决方案?使用相同格式和尺寸的 D3D11_CPU_ACCESS_WRITE 创建 D3D11_USAGE_STAGING 资源,使用例如 CPU 更新它Map/Unmap,然后调用 ID3D11DeviceContext::CopyResource 从暂存资源复制到 UA 资源。
假设我有
ID3D11UnorderedAccessView* pDataView
我有
byte* pRawData
如何使用 pRawData 设置 pDataView 的缓冲区?
注意:FAILED 和 CHR 是错误检查宏。
更新:当我创建无人机时,Soonts 给出了一个似乎可以解决问题的答案,但为了完整性,我还希望能够从 CPU 在两者都被创建之后。我没有那么成功地尝试过。如果我有:
template <typename T>
static inline void CreateUnorderedAccessViewFromFile(
_In_ ID3D11Device* pDevice,
_In_ ID3D11DeviceContext* pDeviceContext,
_In_ HANDLE dataFile,
_Out_ ID3D11Buffer** ppBuffer,
_Out_ ID3D11UnorderedAccessView** ppUav)
{
uint64_t fileSize;
//CBR(::GetFileSizeEx(handle, &fileSize));
//Custom size for testing purposes
fileSize = 0x800;
D3D11_BUFFER_DESC bufferDesc =
{
fileSize, // ByteWidth
D3D11_USAGE_DEFAULT, // Usage
D3D11_BIND_UNORDERED_ACCESS, // BindFlags
D3D11_CPU_ACCESS_WRITE, // CPUAccessFlags
D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, // MiscFlags
sizeof(T), // StructureByteStride
};
CHR(pDevice->CreateBuffer(
&bufferDesc,
nullptr,
ppBuffer));
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = pDeviceContext->Map(
*ppBuffer,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&mappedResource);
byte* ppData = reinterpret_cast<byte*>(mappedResource.pData);
for (uint64_t i = 0; i < fileSize; i += 0x10000)
{
DWORD readSize = min(fileSize - i, 0x10000);
if (!ReadFile(
dataFile,
ppData,
readSize,
NULL,
NULL))
{
uint32_t lastError = ::GetLastError();
CBR(lastError != ERROR_IO_PENDING);
}
}
pDeviceContext->Unmap(
*ppBuffer,
0);
D3D11_UNORDERED_ACCESS_VIEW_DESC uaView =
{
DXGI_FORMAT_UNKNOWN, // Format
D3D11_UAV_DIMENSION_BUFFER, // ViewDimension
};
uaView.Buffer.FirstElement = 0;
uaView.Buffer.Flags = 0;
uaView.Buffer.NumElements = fileSize / sizeof(T);
CHR(pDevice->CreateUnorderedAccessView(
*ppBuffer,
&uaView,
ppUav));
}
为什么我会 E_INVALIDARG 在地图上?
注意:FAILED 和 CHR 是错误检查宏。
首先您需要为您的数据创建一个缓冲区。
如果您的数据是 2D 纹理,请调用 ID3D11Device::CreateTexture2D。不要忘记 D3D11_TEXTURE2D_DESC::BindFlags 字段中的 D3D11_BIND_UNORDERED_ACCESS。您可以在 D3D11_SUBRESOURCE_DATA 结构中的第二个参数中传递 byte* pRawData
。
如果您的数据是一维结构数组,请调用 ID3D11Device::CreateBuffer,您应该再次传递 D3D11_BIND_UNORDERED_ACCESS 和您的初始数据。
无人机还支持其他类型的资源:1D 纹理、1D 纹理数组、2D 纹理数组、3D 纹理。这完全取决于您的数据,以及处理该数据的着色器。
最后,调用 ID3D11Device::CreateUnorderedAccessView 传递 ID3D11Texture2D、ID3D11Buffer 或其他一些资源。 ID3D11Texture2D、ID3D11Buffer等都是继承自ID3D11Resource,所以你可以传其中一个。
更新: 如果您已经创建了两者并且您只需要更新,请在您的 pDataView 上调用 GetResource 以从视图中获取资源。然后更新缓冲区 ID3D11DeviceContext::Map、memcpy、ID3D11DeviceContext::Unmap。只要确保您已经创建了允许这样做的资源,即 D3D11_CPU_ACCESS_WRITE.
更新: 正如评论者所说,您不能直接从 CPU 更新无人机资源。解决方案?使用相同格式和尺寸的 D3D11_CPU_ACCESS_WRITE 创建 D3D11_USAGE_STAGING 资源,使用例如 CPU 更新它Map/Unmap,然后调用 ID3D11DeviceContext::CopyResource 从暂存资源复制到 UA 资源。