0
\$\begingroup\$

I am trying to send video data from Dolphin Emulator to another process. To do so, I first get a reference to the back buffer from the swap chain.

// in file: D3DGfx.cpp 
// in function: void Gfx::PresentBackBuffer()
  HRESULT hr = m_swap_chain->GetDXGISwapChain()->GetBuffer(
      0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(back_buffer.GetAddressOf()));

I then create a shared texture and do a GPU -> GPU copy so I can modify the texture later.

  D3D11_TEXTURE2D_DESC desc;
  ComPtr<ID3D11Texture2D> shared_texture;

  back_buffer->GetDesc(&desc);

  desc.BindFlags = 0;
  desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;

  hr = D3D::device->CreateTexture2D(&desc, nullptr, shared_texture.GetAddressOf());

  D3D::context->CopyResource(shared_texture.Get(), back_buffer.Get());

Then, I create a shared handle, and map it to shared memory with my other process for reading.

  hr = shared_texture.As(&dxgi_resource);
  hr = dxgi_resource->GetSharedHandle(&shared_handle);
  void* pMappedMem = MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0,
                                   32);  // map 32 bytes into the virtual address space
  struct SharedTextureData sd;
  sd.handle = shared_handle;
  sd.width = width;
  sd.height = height;
  if (pMappedMem)
  {
    std::memcpy(pMappedMem, &sd, sizeof(SharedTextureData));
    UnmapViewOfFile(pMappedMem);
  }

However, before sharing the texture, I wanted to debug the texture to make sure I was sending the proper data. So I created a staging texture, mapped the resource, and saved to png to view the texture.

  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;  // Allow CPU read access
  desc.Usage = D3D11_USAGE_STAGING;
  ComPtr<ID3D11Texture2D> staging_texture;
  hr = D3D::device->CreateTexture2D(&desc, nullptr, staging_texture.GetAddressOf());
  D3D::context->CopyResource(staging_texture.Get(), shared_texture.Get());

  D3D11_MAPPED_SUBRESOURCE mappedResource;
  hr = D3D::context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mappedResource);

  BYTE* data = reinterpret_cast<BYTE*>(mappedResource.pData);
  UINT rowPitch = mappedResource.RowPitch;

  //save to png
  stbi_write_png("output.png", width, height, 4, data, rowPitch);

This is the texture that was saved. Distorted Texture

For reference, this is what the texture looks like after being drawn to the screen by Dolphin Emulator. Actual Texture

Things I have tried to resolve this issue but did not change anything or made it worse:

  • Ensure that the format is correct (DXGI_FORMAT_R10G10B10A2_UNORM)

  • Adjust the format to be PNG-compatible:

      for (UINT i = 0; i < desc.Height; ++i)
      {
        for (UINT j = 0; j < mappedResource.RowPitch; j += 4)
        {
          UINT offset = (i * desc.Width + j);
          data[offset] = (data[offset] >> 2) & 0x3F;
          data[offset + 1] = (data[offset] >> 2) & 0x3F;
          data[offset + 2] = (data[offset] >> 2) & 0x3F;
          data[offset + 3] = (data[offset] >> 2) & 0x3F;
    
        }
      }
    

    This results in the following texture: Even more distorted texture

  • Resolve the texture to a single sample (if it was multi-sampled) before copying to the staging texture

      desc.Usage = D3D11_USAGE_DEFAULT;
      desc.SampleDesc.Count = 1;  // Resolve to a single sample
      desc.SampleDesc.Quality = 0;
    
      ComPtr<ID3D11Texture2D> resolvedTexture;
      hr = D3D::device->CreateTexture2D(&desc, nullptr, resolvedTexture.GetAddressOf());
    
      D3D::context->CopyResource(resolvedTexture.Get(), backBuffer.Get());
    
      D3D::context->ResolveSubresource(resolvedTexture.Get(), 0, backBuffer.Get(), 0,
                                       desc.Format);
    
    

If anyone could identify what the cause of the distortion might be, or suggest a better technique or a different approach entirely, I would greatly appreciate it.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think png doesn't supports 10:10:10:2 format. You have to convert it to something like 8:8:8:8 or another (see: datatracker.ietf.org/doc/html/rfc2083#page-16). See also github.com/microsoft/DirectXTex. It might have something to help in the conversion. Otherwise you have to manually convert the 10:10:10:2 to 8:8:8:8. You would have to map that 2 bit channel to 8 bit channel for the png format. So something like 00 -> Fully transparent and 11-> Opaque. But you have to decide for 01 and 10 mapping. And also you have to take the byte order into consideration i.e RGBA or ABGR. \$\endgroup\$ Commented Dec 17, 2024 at 3:13

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.