0

In D3D11_SUBRESOURCE_DATA, we have a const void* that is meant to be used for the initial data of a ID3D11Buffer.

When we use Map, we receive back a void*. Can I safely use a cast to get an object representation of what I initially put into the D3D11_SUBRESOURCE_DATA?

    template <typename CBuff>
    class ConstantBuffer {
        ComPtr<ID3D11Buffer> buffer;

    public:
        ConstantBuffer() = default;
        ConstantBuffer(ID3D11Device* device, CBuff& bufferData) {
            D3D11_BUFFER_DESC desc = {};
            desc.ByteWidth = sizeof(CBuff);
            /* setting usage etc*/
            D3D11_SUBRESOURCE_DATA data{}; // initial buffer data 
            data.SysMemPitch = sizeof(CBuff);
            data.pSysMem = &bufferData; // use passed buffer data
            Utils::throwIfFailed(device->CreateBuffer(&desc, &data, buffer.GetAddressOf()));
        }
        void updateData(CBuff& data,ID3D11DeviceContext* ctx) {
            D3D11_MAPPED_SUBRESOURCE mappedResource;
            HRESULT res = ctx->Map(buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
            if (SUCCEEDED(res)) {
                CBuff* dataPtr = static_cast<CBuff*>(mappedResource.pData); // static_cast or any other cast here
                //do something with dataPtr, like setting members
                ctx->Unmap(buffer.Get(), 0);
            }
        }
    };
Raildex
  • 3,406
  • 1
  • 18
  • 42
  • You can safely cast anything into a pointer to void. And round-trip it back into a pointer to the original type. You are, however, on your honor to ensure that you round-trip it back to a pointer of the exact, original type. Once you use `reinterpret_cast`, the compiler will not check this for you. In fact, I'd argue you should use `static_cast` for a conversion to and from `void*` (but this won't check the semantic correctness, either). See also [this discussion](https://stackoverflow.com/q/310451) on that note. – Cody Gray - on strike Jul 04 '21 at 09:13
  • @CodyGray I've changed my question to be agnostic of the cast to use, but more about whether it is safe in the API environment (D3D11) – Raildex Jul 04 '21 at 09:23
  • Sorry, I guess I don't quite understand. Are you talking about the `pData` member of the `D3D11_MAPPED_SUBRESOURCE` structure that is filled in by the `Map` method? – Cody Gray - on strike Jul 04 '21 at 09:33
  • By design, ``D3D11_MAPPED_SUBRESOURCE`` returns a generic pointer because exactly what the data is how you want to access it really depends on what you are doing. The key thing to remember is it is "rowPitch" bytes for each scanline (for BC formats it's a row of 4x4 blocks; video formats can be weird) and the meaning of each pixel is based on the ``DXGI_FORMAT_`` of the resource. For *lots* of example code, see [DirectXTex](https://github.com/microsoft/DirectXTex). You might want to start with looking at DDSTextureLoader or WICTextureLoader. – Chuck Walbourn Jul 08 '21 at 08:56
  • @ChuckWalbourn in my case i have a class `ConstanBuffer` which is a template where the Type `CBuff` is a class that contains the data of said ConstantBuffer. I was wondering whether I can cast the pointer returned by `Map` to `CBuff`and manipulate the content directly. See my code snippet in the question. – Raildex Jul 08 '21 at 09:34
  • 1
    Absolutely and that's extremely common. See ``ConstantBuffer::SetData`` in the *DirectX Tool Kit for DX11* [here](https://github.com/microsoft/DirectXTK/blob/master/Inc/BufferHelpers.h). – Chuck Walbourn Jul 08 '21 at 17:28
  • @ChuckWalbourn Thank you. can you make an answer so i can accept it? – Raildex Jul 08 '21 at 19:10
  • Alas no since they marked it duplicate – Chuck Walbourn Jul 08 '21 at 21:30

0 Answers0