VRAM size?

BlitzMax Forums/OpenGL Module/VRAM size?

ima747(Posted 2009) [#1]
First off, I'm very very new to the guts of opengl, so apologies if this is crazy easy or stupid.

I know there's a million reasons why you can't get an exact number on available vram, and you shouldn't really need to know, etc.

but according to http://lists.apple.com/archives/mac-opengl/2001/May/msg00022.html atleast on mac it looks like you can find out the max vram of the graphics card, or the max memory opengl is allowed to use.

I don't need byte perfect numbers for vram, I just need to know roughly what the maximum is. In the app I'm working on all the textures are user provided so they can vary wildly (there are some scaling limits I do on them before I make the textures) and there can be HUGE numbers of them provided. So without any way of knowing what the limit of the vram is the user can provide tons of huge images and the system nearly locks up trying to swap them to the graphics card every render. but I don't want to limit it to some arbitrary low number of textures because if they're providing small textures then they can easily handle many many more before the performance chokes. Additionally if they have a 64mb card vs a 1gb card there's a wide range of size/quantity that their system could handle.

So long and short, is there any way (preferably OS/graphics card manufacturer independent) to get a rough idea of how much vram a system has. Closest I've come is there's a registry query you can do for windows and ATI cards and possibly an nvidia driver function for windows that will look up the reported vram. and I found http://lists.apple.com/archives/mac-opengl/2001/May/msg00022.html this thread that looked promising, but I don't know how to/if it's possible to shoe horn that into blitzmax...

It's just a number on the hardware, I find it hard to believe you can't just ask for it... I know why you shouldn't it most cases but it should still exist somewhere...


ImaginaryHuman(Posted 2009) [#2]
Yah I wish someone would code a cross-platform function to just return the total vram. .. the o/s knows what it is, it would just require the appropriate api calls or whatever, presumably, if not too complicated, and if reliable.

You can try allocating proxy textures to test to see if they are successfully created to give you an idea of how much ram there is.

OpenGL doesn't like having system-specific stuff in it like `amount of free memory` because it is cross platform.


ima747(Posted 2009) [#3]
Closest I've gotten so far is to just factor the largest texture the graphics card reports it can support. The theory being a card can't support a texture larger than it's total vram so the number will be either the vram size or a fraction of it. Smaller is safer than too much, and the newer the card the more likely it is to allow 1 texture for the full vram. Providing a manual override for someone who knows their system specs properly and that's the best I've managed so far. It's ugly and wrong but it's better than "OpenGL knows all and does all, have faith in the POWA!" that I read everywhere (as for my app I know I'm exceeding the vram if I don't manage it, and that takes the FPS from 120+ to 0.01 in some circumstances...).

so 32bit
maxtexturesize * maxtexturesize * 4

I can't confirm that all graphics cards won't allow a texture bigger than their vram however if they did it would require CRAZY amounts of memory swapping if anyone ever used it so I seriously doubt they would. It's not accurate at all but atleast it should give a safe number...


ImaginaryHuman(Posted 2009) [#4]
So a 4096x4096 texture takes up 67 megabytes, so that would tell you... that it has 128 vram?


ima747(Posted 2009) [#5]
4096 pixel * 4096 pixels * 4 bytesPerPixel = 64mb

So it has at least 64mb. Which is better than the nothing I knew before (but not by a whole lot)

Still working on an OS dependent query. I found a function for mac in C that should do it, and in theory a directx query on windows should be able to tell you since dxdiag knows (sort of) how much vram the card has...

I'm still kinda shocked at how badly they don't want you to know something so important if you have any interest in taking advantage of a card's capacity. It's a critical number if you want to scale the quality of your textures for the hardware capacity or if you (like me) can control how many you have on screen at one time...


ima747(Posted 2009) [#6]
Here's what I've got, seems to work on mac, though I haven't tested it on a multi head or multi card system yet to figure out if the primary display is always 0 etc. Returns the vram size in bytes.

VramSize.bmx
SuperStrict

?MacOS
	Import "macvram.c"
	Private
		Extern
			Function MACOS_GetVramSize:Int(displayID:Int)"C"
		EndExtern
	Public
?


Function GetVramSize:Int(displayNumber:Int)
	?Win32
		Return -1
	?MacOS
		Return MACOS_GetVramSize(displayNumber)
	?Linux
		Return -1
	?
EndFunction


macvram.c
// macvram.c

#include <ApplicationServices/ApplicationServices.h>

long MACOS_GetVramSize( int displayNumber )
{
	long displaySize = -1;
	long *vramArray;
	int dispCount = vramSize(&vramArray);
	if(displayNumber < dispCount && displayNumber >= 0) {
		displaySize = vramArray[displayNumber];
	}
	return displaySize;
}

int vramSize(long** vsArray)
{
    CGError                    err = CGDisplayNoErr;
    int                            i = 0;
    io_service_t              *dspPorts = NULL;
    CGDirectDisplayID    *displays = NULL;
    CGDisplayCount        dspCount = 0;
    CFTypeRef                 typeCode;
	
    // How many active displays do we have?
    err = CGGetActiveDisplayList(0, NULL, &dspCount);
	
    // Allocate enough memory to hold all the display IDs we have
    displays = calloc((size_t)dspCount, sizeof(CGDirectDisplayID));
    // Allocate enough memory for the number of displays we're asking about
    *vsArray = calloc((size_t)dspCount, sizeof(long));
    // Allocate memory for our service ports
    dspPorts = calloc((size_t)dspCount, sizeof(io_service_t));
	
    // Get the list of active displays
    err = CGGetActiveDisplayList(dspCount,
                                 displays,
                                 &dspCount);
	
    // Now we iterate through them
    for(i = 0; i < dspCount; i++)
    {
        // Get the service port for the display
        dspPorts[i] = CGDisplayIOServicePort(displays[i]);
        // Ask IOKit for the VRAM size property
        typeCode = IORegistryEntryCreateCFProperty(dspPorts[i],
                                                   CFSTR(kIOFBMemorySizeKey),
                                                   kCFAllocatorDefault,
                                                   kNilOptions);
		
        // Ensure we have valid data from IOKit
        if(typeCode && CFGetTypeID(typeCode) == CFNumberGetTypeID())
        {
            // If so, convert the CFNumber into a plain unsigned long
            CFNumberGetValue(typeCode, kCFNumberSInt32Type, vsArray[i]);
            if(typeCode)
				CFRelease(typeCode);
        }
    }
	// Return the total number of displays we found
	return (int)dspCount;
}


in macvram.c vramsize() is taken directly from an apple Q&A document and reformated for C instead of ObjectiveC (I don't know if the blitz compiler will play with objective C and I don't want to find out...). And then MACOS_GetVramSize() is just a wrapper for that to pick out the vram for the display. I don't remember enough about the mac garbage collector to know if this might leak the display array or not. it could also be reformatted into 1 function quite easily... Formatted the function name with the intent of inclusion in the chaos.desktopext mod, as I think (once it's cross platform) that would be a good home for it if they're interested.

As with any other discussion of vram remember that just because it's there you don't own it or have direct control so use the number with that in mind, it's just a point of reference.

Anyone know how to query directX for the vram? or ask around in linux?


beanage(Posted 2009) [#7]
For Windows, I found this:

The DirectDraw4 [IDirectDraw4] class has a method [IDirectDraw4::GetAvailableVidMem]. Unfortunately, I got no idea how to access it.


ima747(Posted 2009) [#8]
Thanks, that looks promising. Additionally second to last post here recommends the same method in DX7 with some specific options to help compensate for inherent flaws with this method.

I may try to dig into DX a little to get this going but I've never had luck with it in the past, let alone embeded under blitzmax so if anyone has any thoughts or experience they can share it would be great. I'm thinking something along the lines of using setgraphicsdriver to directx and graphics to init the draw space, and somehow getting it's address to pass along to the GetAvailableVidMem()...


ima747(Posted 2009) [#9]
I think one needs to call GetCaps() to fill the CAPS to send to GetAvailableVidMem()... this is the kind of nonsense, acronymtasticness that made me give up on trying to learn DirectX many many years ago...


ima747(Posted 2009) [#10]
another example with some more code, where does one get lpdd from? and what is it?

Update: lpdd is a french acronym for The Apple Of Discord, which seems quite fitting to me right now, if not helpfull...


ima747(Posted 2009) [#11]
digging through Pub.DirectX mod it looks like GetCaps is already implemented, and further more in the caps types for various direct draw versions there is a value for dwVidMemTotal. However I don't know how to get an initlialized IDirectDraw type to call it's GetCaps method to fill a DDSCAPS2 type to access it's dwCaps field to access THAT field's dwVidMemTotal field...

SO. Sorry to be asking a directx question in an OpenGL forum, but the threads here for now so I will. How doe I get an IDirectDraw type up and running?