在分派我的着色器之前,如何写入ID3D11UnorderedAccessView的缓冲区?

时间:2017-05-29 23:02:41

标签: c++ shader directx-11

假设我有

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是错误检查宏。

1 个答案:

答案 0 :(得分:1)

首先,您需要使用数据创建缓冲区。

如果您的数据是2D纹理,请致电ID3D11Device::CreateTexture2D。不要忘记D3D11_TEXTURE2D_DESC :: BindFlags字段中的D3D11_BIND_UNORDERED_ACCESS。你可以在第二个参数中传递byte* pRawData,即D3D11_SUBRESOURCE_DATA结构。

如果您的数据是一维结构数组,请再次调用ID3D11Device::CreateBuffer,您应该传递D3D11_BIND_UNORDERED_ACCESS和您的初始数据。

无人机支持其他类型的资源:1D纹理,1D纹理数组,2D纹理数组,3D纹理。这一切都取决于您的数据,以及着色器处理它。

最后,通过ID3D11Texture2D或ID3D11Buffer或其他资源调用ID3D11Device::CreateUnorderedAccessView。 ID3D11Texture2D,ID3D11Buffer和其他都继承自ID3D11Resource,因此您可以传递其中任何一个。

更新:如果您已经创建了两个并且只需要更新,请在pDataView上调用GetResource以从视图中获取资源。然后更新缓冲区ID3D11DeviceContext :: Map,memcpy,ID3D11DeviceContext :: Unmap。只需确保您已创建允许该资源的资源,即D3D11_CPU_ACCESS_WRITE。

更新:正如评论者所说,您无法直接从CPU更新UAV资源。解决方案?使用相同格式和尺寸的D3D11_CPU_ACCESS_WRITE创建D3D11_USAGE_STAGING资源,使用例如CPU从CPU更新它。映射/取消映射,然后调用ID3D11DeviceContext::CopyResource从登台资源复制到UA资源。