1

For testing purposes I need a tool that will occupy some amount of VRAM, leaving a reduced available VRAM to the rest of the applications. I implemented a version that somewhat works using D3D12 API, but it has a problem of allocated resources being demoted to Shared RAM, thus leaving more available VRAM to tested application than anticipated.

Is there a way to make sure the allocation will not be demoted like this and will stay in hardware VRAM for the whole duration irrespective of the rest of applications' GPU usage?

Here is the snippet on how the allocation is implemented in my current version (uses Odin language bindings to D3D12). I use L1 memory pool preference, which is supposed to be GPU-only pool, but seems like it still can work with shared memory:

resources: [dynamic]^dx.IResource
allocated_bytes: u64 = 0
chunk_size: u64 = 64 * 1024 * 1024 // 64 MB chunks

// Allocate chunks of set size + a left-over chunk of remaining size
for allocated_bytes < target_bytes {
    actual_chunk := min(chunk_size, target_bytes - allocated_bytes)
    
    heap_props := dx.HEAP_PROPERTIES {
        Type = .CUSTOM,
        CPUPageProperty = .NOT_AVAILABLE,
        MemoryPoolPreference = .L1,
        CreationNodeMask = 1,
        VisibleNodeMask = 1,
    }
    
    resource_desc := dx.RESOURCE_DESC {
        Dimension = .BUFFER,
        Alignment = 0,
        Width = actual_chunk,
        Height = 1,
        DepthOrArraySize = 1,
        MipLevels = 1,
        Format = .UNKNOWN,
        SampleDesc = { Count = 1, Quality = 0 },
        Layout = .ROW_MAJOR,
        Flags = {},
    }
    
    resource: ^dx.IResource
    hr := ctx.device->CreateCommittedResource(
        &heap_props,
        {}, // heap flags
        &resource_desc,
        {}, // resource states
        nil, // clear value
        dx.IResource_UUID,
        cast(^rawptr)&resource,
    )
    
    if hr < 0 {
        // If we can't allocate the full chunk, try a smaller chunk
        MIN_CHUNK_SIZE :: 1024 * 1024
        if chunk_size > MIN_CHUNK_SIZE { 
            chunk_size = chunk_size / 2
            continue
        }
        
        fmt.printfln("\nFailed to allocate more VRAM (error %d). VRAM might be full or fragmented.", hr)
        break
    }

    append(&resources, resource)
    allocated_bytes += actual_chunk
    fmt.printf("Allocated           : %.2f GB / %.2f GB\r", bytes_to_gb(allocated_bytes), bytes_to_gb(target_bytes))
}

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.