WELCOME TO INFOCHEATS.NET

INFOCHEATS is a community-driven platform focused on free game cheats, cheat development, and verified commercial software for a wide range of popular games. We provide a large collection of free cheats shared by the community. All public releases are checked for malicious code to reduce the risk of viruses, malware, or unwanted software before users interact with them.

Alongside free content, INFOCHEATS hosts an active marketplace with many independent sellers offering commercial cheats. Each product is discussed openly, with user feedback, reviews, and real usage experience available to help you make informed decisions before purchasing.

Whether you are looking for free cheats, exploring paid solutions, comparing sellers, or studying how cheats are developed and tested, INFOCHEATS brings everything together in one place — transparently and community-driven.

Question DXGI Desktop Duplication — Capturing Empty Black/Transparent Frames

byte_corvus

Newbie
Newbie
Newbie
Newbie
Status
Offline
Joined
Mar 3, 2026
Messages
546
Reaction score
7
Digging into the DXGI API for a screen capture module and I've hit a wall that's likely familiar to anyone messing with the Desktop Duplication API. I'm trying to pull frames for an external project, and while the code executes without a single HRESULT error, the actual output is a void.

The Symptom:
Everything returns S_OK, but the buffer is essentially zeroed out. If I save as BGR, it's a black void. If I save as BGRA, it's 100% transparent. This usually smells like a staging texture issue or a synchronization failure between the GPU and CPU buffers.

The Current Setup:
  1. D3D11 Device and DXGI Device initialization.
  2. Desktop Duplication setup via IDXGIOutputDuplication.
  3. Acquiring the frame using AcquireNextFrame.
  4. Copying to a CPU-accessible texture and saving to BMP.

Frame Capture Logic:
Code:
BYTE* GetFrameAsBitmap(CAPTURE& capturer, int& width, int& height) {
    DXGI_OUTDUPL_FRAME_INFO frameInfo;
    CComPtr<IDXGIResource> desktopResource;
    HRESULT hr = capturer.lDeskDupl->AcquireNextFrame(0, &frameInfo, &desktopResource);
    
    if (SUCCEEDED(hr)) {
        if (!capturer.Get(desktopResource, false)) {
            capturer.lDeskDupl->ReleaseFrame();
            return nullptr;
        }
        capturer.lDeskDupl->ReleaseFrame();
    }
    
    width = capturer.lOutputDuplDesc.ModeDesc.Width;
    height = capturer.lOutputDuplDesc.ModeDesc.Height;
    
    return capturer.buf.data();
}

Main Invocation:
Code:
void main() {
    CAPTURE capture = CAPTURE();
    HRESULT hr = capture.CreateDirect3DDevice(nullptr);
    
    if (FAILED(hr)) {
        std::cerr << "Failed to create D3D device!" << std::endl;
        return;
    }

    if (!capture.Prepare(0)) {
        std::cerr << "Failed to prepare screen capture!" << std::endl;
        return;
    }

    int width, height;
    BYTE* bitmap = GetFrameAsBitmap(capture, width, height);

    if (bitmap) {
        SaveBitmapToFile(bitmap, width, height, "screenshot.bmp");
    }
}

Code:
void SaveBitmapToFile(const BYTE* bitmap, int width, int height, const char* filename) {
    int bytesPerPixel = 4; 
    int rowSize = width * bytesPerPixel;
    int padding = (4 - (rowSize % 4)) % 4;
    
    std::vector<BYTE> bmpData((rowSize + padding) * height);

    for (int y = 0; y < height; y++) {
        int srcIndex = (height - 1 - y) * width * bytesPerPixel;
        int dstIndex = y * (width * bytesPerPixel + padding);
        for (int x = 0; x < width; x++) {
            bmpData[dstIndex + x * 3 + 0] = bitmap[srcIndex + x * 4 + 0]; // B
            bmpData[dstIndex + x * 3 + 1] = bitmap[srcIndex + x * 4 + 1]; // G
            bmpData[dstIndex + x * 3 + 2] = bitmap[srcIndex + x * 4 + 2]; // R
        }
    }

    BITMAPFILEHEADER fileHeader = {0x4D42, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmpData.size(), 0, 0, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)};
    BITMAPINFOHEADER infoHeader = {sizeof(BITMAPINFOHEADER), width, height, 1, 24, BI_RGB, (DWORD)bmpData.size(), 0, 0, 0, 0};

    std::ofstream file(filename, std::ios::binary);
    file.write((char*)&fileHeader, sizeof(fileHeader));
    file.write((char*)&infoHeader, sizeof(infoHeader));
    file.write((char*)bmpData.data(), bmpData.size());
}

The Core Problem:
I've verified that AcquireNextFrame is returning S_OK and the pointer isn't null. I'm using the standard DXGI_FORMAT_B8G8R8A8_UNORM. Despite this, the pixel data is just not there. I suspect the issue might be in how the resource is being mapped or the staging texture is handled within the library helper, but I've tried a few different implementations with the same result.

Could this be related to multi-GPU setups or specifically how Windows handles the desktop duplication slot?

anyone encountered this with multi-monitor setups or specific TDR settings?
 
Top