Search code examples
ffmpegmappingdirectx-11memcpytexture2d

rgb32 data resource mapping. using directx memcpy


I have been trying to solve the problem for a month with googling. But Now I have to ask for help here.

I want to render using ffmpeg decoded frame. and using frame(it converted to RGB32 format), I try to render frame with DX2D texture.

ZeroMemory(&TextureDesc, sizeof(TextureDesc));

TextureDesc.Height = pFrame->height;
TextureDesc.Width = pFrame->width;
TextureDesc.MipLevels = 1;
TextureDesc.ArraySize = 1;
TextureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;            //size 16
TextureDesc.SampleDesc.Count = 1;
TextureDesc.SampleDesc.Quality = 0;
TextureDesc.Usage = D3D11_USAGE_DYNAMIC;
TextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
TextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
TextureDesc.MiscFlags = 0;

result = m_device->CreateTexture2D(&TextureDesc, NULL, &m_2DTex);
if (FAILED(result))     return false;

ShaderResourceViewDesc.Format = TextureDesc.Format;
ShaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
ShaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
ShaderResourceViewDesc.Texture2D.MipLevels = 1;

    D3D11_MAPPED_SUBRESOURCE S_mappedResource_tt = { 0, };

ZeroMemory(&S_mappedResource_tt, sizeof(D3D11_MAPPED_SUBRESOURCE));

result = m_deviceContext->Map(m_2DTex, 0, D3D11_MAP_WRITE_DISCARD, 0, &S_mappedResource_tt);
if (FAILED(result)) return false;
BYTE* mappedData = reinterpret_cast<BYTE *>(S_mappedResource_tt.pData);
for (auto i = 0; i < pFrame->height; ++i) {
    memcpy(mappedData, pFrame->data, pFrame->linesize[0]);
    mappedData += S_mappedResource_tt.RowPitch;
    pFrame->data[0] += pFrame->linesize[0];
}

m_deviceContext->Unmap(m_2DTex, 0);

result = m_device->CreateShaderResourceView(m_2DTex, &ShaderResourceViewDesc, &m_ShaderResourceView);
if (FAILED(result))     return false;

    m_deviceContext->PSSetShaderResources(0, 1, &m_ShaderResourceView);

but it shows me just black screen(nothing render). I guess it's wrong memcpy size. The biggest problem is that I don't know what is the problem.

Question 1 : It has any problem creating 2D texture for mapping?

Question 2 : What size of the memcpy parameters should I enter (related to formatting)?

I based on the link below.

[1]https://www.gamedev.net/forums/topic/667097-copy-2d-array-into-texture2d/ [2]https://www.gamedev.net/forums/topic/645514-directx-11-maping-id3d11texture2d/ [3]https://www.gamedev.net/forums/topic/606100-solved-dx11-updating-texture-data/

Thank U for watching, Please reply.


Solution

  • Nobody reply. I solved my issue. I have modified some code and I'm not sure if it solves the problem. The problem with the black screen Reason is my matrix.

    D3D11_TEXTURE2D_DESC TextureDesc;
    D3D11_RENDER_TARGET_VIEW_DESC RenderTargetViewDesc;
    D3D11_SHADER_RESOURCE_VIEW_DESC ShaderResourceViewDesc;
    
    ZeroMemory(&TextureDesc, sizeof(TextureDesc));
    
    TextureDesc.Height = pFrame->height;
    TextureDesc.Width = pFrame->width;
    TextureDesc.MipLevels = 1;
    TextureDesc.ArraySize = 1;
    TextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;/*DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;*/            //size 32bit
    TextureDesc.SampleDesc.Count = 1;
    TextureDesc.SampleDesc.Quality = 0;
    TextureDesc.Usage = D3D11_USAGE_DYNAMIC;
    TextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    TextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    TextureDesc.MiscFlags = 0;
    
    DWORD*  pInitImage = new DWORD[pFrame->width*pFrame->height];
    memset(pInitImage, 0, sizeof(DWORD)*pFrame->width*pFrame->height);
    D3D11_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = pInitImage;
    InitData.SysMemPitch = pFrame->width*sizeof(DWORD);
    InitData.SysMemSlicePitch = 0;
    result = m_device->CreateTexture2D(&TextureDesc, &InitData, &m_2DTex);
    if (FAILED(result))     return false;
    
    ShaderResourceViewDesc.Format = TextureDesc.Format;
    ShaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    ShaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
    ShaderResourceViewDesc.Texture2D.MipLevels = 1;
    
    result = m_device->CreateShaderResourceView(m_2DTex, &ShaderResourceViewDesc, &m_ShaderResourceView);
    if (FAILED(result))     return false;
    
    D3D11_MAPPED_SUBRESOURCE S_mappedResource_tt;
    ZeroMemory(&S_mappedResource_tt, sizeof(S_mappedResource_tt));
    DWORD   Stride = pFrame->linesize[0];
    
    result = m_deviceContext->Map(m_2DTex, 0, D3D11_MAP_WRITE_DISCARD, 0, &S_mappedResource_tt);
    if (FAILED(result)) return false;
    
    BYTE * pFrameData = pFrame->data[0];   // now we have a pointer that points to begin of the destination buffer
    BYTE* mappedData = (BYTE *)S_mappedResource_tt.pData;// +S_mappedResource_tt.RowPitch;
    for (auto i = 0; i < pFrame->height; i++) {     
        memcpy(mappedData, pFrameData, Stride);
        mappedData += S_mappedResource_tt.RowPitch;
        pFrameData += Stride;
    }
    
    m_deviceContext->Unmap(m_2DTex, 0);
    

    It works vell. I hope that it will be helpful to those who are doing the same thing with me.