Jump to content

  • Log In with Google      Sign In   
  • Create Account

The jump to DirectX11 : Setup questions


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 27 October 2013 - 09:09 AM

I got a ton of questions about how to do proper set up for Direct x 11, maily because I'm not sure what needs to be checked for and the tutorials on this seem to be a little lackluster. So if I leave anything out please let me know.

 

Currently I do the following

1. Create a factory

2. Use the facotry to get all the available display adapters

3. Based on the first display adapter we find, get all the available display modes that are of Scaling type

4. Create the device

5. Create the swapchian based on the 800 x 600 diplsay mode found

6. Create the backbuffer render target and viewport

 

Now I have some issues:

 

Question 1

 

When getting the available display adapters I use this code:

	for(UINT i = 0; deviceFactory->EnumAdapters(i, &currentDeviceAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
	{
		availableDeviceAdapters.push_back(currentDeviceAdapter);
	}
	currentDeviceAdapter = availableDeviceAdapters[0];

	currentDeviceAdapter->GetDesc(&currentAdapterDescription);
	std::wcout<<"Available Adapter:"<<currentAdapterDescription.Description<<std::endl;
	std::cout<<"Finished getting adapters"<<std::endl;
	getchar();

When I do clean up though using:

	//Works on clean up
        if(currentDeviceAdapter != NULL)
		currentDeviceAdapter->Release();
	
	
	//Breaks in here
	for(std::vector<IDXGIAdapter*>::iterator i = availableDeviceAdapters.begin(); i != availableDeviceAdapters.end(); i++)
	{
            //Breaks here even when checking for NULL
	    if((*i) != NULL)
		(*i)->Release();
	}
	availableDeviceAdapters.clear();
	

I get a accesss violation, how am I supposed to properly clean this up?

My variables are declared like so

IDXGIAdapter *currentDeviceAdapter;
std::vector<IDXGIAdapter*> availableDeviceAdapters;

Question 2

 

In Direct X 9 I got Direct X ready first and then created my window based on the resolution I wanted to use.

Eg: Loop through all teh supported resolutions and pick 800 x 600; If it was unavailable fallback to a 640 x 480 resolution.

 

It seems this can not be done in Direct X 11, unless I create window first the the swapchain creation fails. Which sort of makes sense since the OutputWindow cannot be NULL according to the documentation. But is there away arround this? Or do I need to be adjusting my window size after direct x is setup? Do I have any special checks in the window's callback function for this to happen?

 

Question 3

My final question... for now at least

 

What happened to checking device caps in Direct X 11? How do I check if the adapter I use is able to support feature X or use something Y?

Eg: The format used when creating the swap chain. Right now I use DXGI_FORMAT_R8G8B8A8_UNORM. But what if someone can't support this?



Sponsor:

#2 Zaoshi Kaba   Crossbones+   -  Reputation: 4356

Like
0Likes
Like

Posted 27 October 2013 - 09:38 AM

DirectX 10 and 11 removed caps, therefore ALL features are supported (there's list of minimal requirements, but hardware might support better ones), however it seems caps are back in 11.1 and/or 11.2 but I hope they'll be gone in DirectX 12 (I prefer to think 11.1 and 11.2 are experiments).


Edited by Zaoshi Kaba, 27 October 2013 - 09:39 AM.


#3 Adam_42   Crossbones+   -  Reputation: 2508

Like
0Likes
Like

Posted 27 October 2013 - 12:06 PM

The reason for the crash is that you're releasing availableDeviceAdapters[0] twice. Once is enough.

 

For a list of supported DX11 texture and render target formats look at http://msdn.microsoft.com/en-us/library/windows/desktop/ff471325%28v=vs.85%29.aspx and the other similar pages linked in the left column for DX10 class hardware.



#4 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 27 October 2013 - 01:30 PM

DirectX 10 and 11 removed caps, therefore ALL features are supported (there's list of minimal requirements, but hardware might support better ones), however it seems caps are back in 11.1 and/or 11.2 but I hope they'll be gone in DirectX 12 (I prefer to think 11.1 and 11.2 are experiments).

 

Hmmm good to know, I assume this includes shader versions? Does this mean if I wanted to use Shader 3.0 I could and be ok with targeting DX 9, DX 10, DX 11?

 

 

The reason for the crash is that you're releasing availableDeviceAdapters[0] twice. Once is enough.

 

I believe you are right, seeing as if I flip the code to roll through the adapter vector first the application breaks on the the release call of the currentDeviceAdapter.

 

But what I don't understand is when the break is being thrown even if I check for NULL.

 

I updated the code to use a For Loop based on the adapter vectors size, because for some odd reason I was getting a vector iterator incompatible assertion break. Even if there was nothing in the For Loop. I'm not sure if this is the best way to do it or it's exactly the same thing as basing the For Loop on a iterator

 

Here is the updated code:

	if(currentDeviceAdapter != NULL)
	{
		currentDeviceAdapter->Release();
		currentDeviceAdapter = NULL;
	}
	
	//Clean up the vector of adapters
	for(UINT i = 0; i < availableDeviceAdapters.size(); i++)
	{
		if(availableDeviceAdapters[i] != NULL)
		{
			availableDeviceAdapters[i]->Release(); //<------ Still breaks here
			availableDeviceAdapters[i] = NULL;
		}
	}

Any ideas why it's breaking even though I check for NULL? It just says applcaition.exe has triggered a break point



#5 backstep   Members   -  Reputation: 335

Like
0Likes
Like

Posted 27 October 2013 - 02:28 PM

Any ideas why it's breaking even though I check for NULL? It just says applcaition.exe has triggered a break point


If I'm reading your code correctly, both currentDeviceAdapter and availableDeviceAdapter[0] are IDXGIAdapter* pointers, that point to the same COM object.

Releasing currentDeviceAdapter releases the single COM object that they both point to. So when you loop through availableDeviceAdapters, then the first entry [0] still points to the same COM object you already just released. The pointer isn't NULL, so the check passes, but the pointed object is already released so the release fails.

Either addref when you assign availableDeviceAdapters[0] to currentDeviceAdapter, so that the number of releases makes sense, or just release only using your availableDeviceAdapters loop, and simply set currentDeviceAdapter = NULL without calling release on it.

Edit:

Probably best to explain how release and addref work. When you create a COM object like IDXGIAdapter, you pass in a pointer that gets assigned the address of the COM object. The COM object that is pointed to automatically has it's reference count incremented during creation, since by default it has that one pointer referencing it. The reason for the reference count is to manage the lifetime of the object, since the object is only needed so long as something is referencing it (either the runtime itself, or an external pointer in your application).

when you call release on a COM object it's reference count is decremented by one. When the reference count reaches zero, the COM object is destroyed. Any pointers that pointed to the object now point to memory that doesn't contain a COM object anymore.

In your case you have two pointers referencing the same COM object, but the object's reference count is only 1, which was incremented during object creation. So to resolve the situation you can either decide one of the pointers is the sole owner of the COM object and only that is responsible for releasing it (I suggested the availableDeviceAdapters array above), or you can addref the COM object when you make a second pointer also reference it (which will increment it's reference count to 2).

In the latter case, your currentDeviceAdapter release call would decrement the object's ref count from 2 to 1, then your availableDeviceAdapter release call will decrement the ref count from 1 to 0 and the COM object is destroyed.

Edited by backstep, 27 October 2013 - 03:30 PM.


#6 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 27 October 2013 - 05:22 PM

< Super awesome explanation >

 

Hmm I find this interesting. I thought we you would release something it would also make the pointer NULL.

 

Now I have classes and other parts of my code where other COM objects are referenced. Like this:

//In Header file
SpriteBatcher(ID3D11Device *&device, ID3D11DeviceContext *&deviceContext);
ID3D11Device *batDevice;
ID3D11DeviceContext *batDeviceContext;

//Constructor of CPP file
SpriteBatcher::SpriteBatcher(ID3D11Device *&device, ID3D11DeviceContext *&deviceContext)
{
	batDevice = device;
	batDeviceContext = deviceContext;
}

//Deconstrcutor of CPP file
SpriteBatcher::~SpriteBatcher()
{
	if(batDevice != NULL)
	{
		batDevice->Release();
		batDevice = NULL;
	}

	if(batDeviceContext != NULL)
	{
		batDeviceContext->Release();
		batDeviceContext = NULL;
	}

        /* Other clean up items */
}

//In the MAIN CPP variable section
SpriteBatcher *batcher;

//In the MAIN CPP startup method
batcher = new SpriteBatcher(system.device, system.deviceContext);

//In the MAIN CPP Clean Up
if(batcher != NULL)
{
   delete batcher;
   batcher = NULL;
}

Now if I run the code it breaks on the backbuffer object in my system clean up

if(backbuffer != NULL)
{
	backbuffer->Release();
	backbuffer = NULL;
}

Should it not the device and device context clean up instead?



#7 backstep   Members   -  Reputation: 335

Like
0Likes
Like

Posted 27 October 2013 - 05:45 PM

What is backbuffer, an ID3D11Texture2D* ?

Retrieved with swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),(LPVOID*)&backbuffer) ?

If more than one pointer points to the same address as backbuffer, and you've already released that pointer, it's the same problem as before and so backbuffer is calling release on a destroyed object.

If backbuffer is the only pointer that points to that address in your app, I'm not sure. If no pointers are referencing the backbuffer's texture2D COM object, it's usually destroyed when your swapchain object is destroyed.

I'd double check how many times you call release on that backbuffer pointer in your entire app, and if you ever copy backbuffer to another pointer in the entire app.

I'm guessing that once you fix the issue with the backbuffer, the device and context will error, since like you say, you've already destroyed them with the release calls in the spritebatcher destructor (assuming you never addref'd them when you copied the system.device and system.context pointers to the spritebatcher member pointers, the actual COM objects only have 1 ref count).

#8 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 27 October 2013 - 05:54 PM

What is backbuffer, an ID3D11Texture2D* ?

Retrieved with swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),(LPVOID*)&backbuffer) ?

If more than one pointer points to the same address as backbuffer, and you've already released that pointer, it's the same problem as before and so backbuffer is calling release on a destroyed object.

If backbuffer is the only pointer that points to that address in your app, I'm not sure. If no pointers are referencing the backbuffer's texture2D COM object, it's usually destroyed when your swapchain object is destroyed.

I'd double check how many times you call release on that backbuffer pointer in your entire app, and if you ever copy backbuffer to another pointer in the entire app.

I'm guessing that once you fix the issue with the backbuffer, the device and context will error, since like you say, you've already destroyed them with the release calls in the spritebatcher destructor (assuming you never addref'd them when you copied the system.device and system.context pointers to the spritebatcher member pointers, the actual COM objects only have 1 ref count).

 

 

Sorry about that, I knew I forgot to mention something, backbuffer is a ID3D11RenderTargetView. I have changed it to backbufferRenderTarget.

 

Currently it is only used by the device and device context. It's created and used like in my systems init method like this:

ID3D11Texture2D *pBackbuffer;
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*) &pBackbuffer);
device->CreateRenderTargetView(pBackbuffer, NULL, &backbufferRenderTarget);
pBackbuffer->Release();

deviceContext->OMSetRenderTargets(1, &backbufferRenderTarget, NULL);

The System.CPP is the only true place where it is touched in terms of Releasing. It's used in the render method:

wyvern.deviceContext->ClearRenderTargetView(wyvern.backbufferRenderTarget, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

But I don't think this is an issue


Edited by noodleBowl, 27 October 2013 - 06:02 PM.


#9 backstep   Members   -  Reputation: 335

Like
0Likes
Like

Posted 27 October 2013 - 06:23 PM

Sorry about that, I knew I forgot to mention something, backbuffer is a ID3D11RenderTargetView. I have changed it to backbufferRenderTarget.
 
Currently it is only used by the device and device context. It's created and used like in my systems init method like this:
ID3D11Texture2D *pBackbuffer;
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*) &pBackbuffer);
device->CreateRenderTargetView(pBackbuffer, NULL, &backbufferRenderTarget);
pBackbuffer->Release();

deviceContext->OMSetRenderTargets(1, &backbufferRenderTarget, NULL);
The System.CPP is the only portion of the application where it is used and referenced


No worries. smile.png

So far as I know the only way to get an RTV to error on release like that, is to try to release it after it's destroyed. It gains one reference on creation ( device->CreateRenderTargetView(pBackbuffer, NULL, &backbufferRenderTarget); ), are you certain it's not released anywhere else in your code?

Even though release was called on the device and context beforehand, they should still exist, because the device's internal reference counter was incremented when you created the ID3D11RenderTargetView that backbufferRenderTarget points to. Internal reference counters are the same as the external reference counters you call addref and release on, except they're only accessible by other COM objects, rather than external pointers, hence the name internal reference counter. The render target view is a child of the device, and won't decrement the device's internal reference count until it's destroyed.

What that means is I don't think the spritebatcher destructor calls to release the device and context are causing your backbufferRenderTarget->Release() exception. The ID3D11RenderTargetView object is somehow already destroyed, meaning it's external ref count was already 0 at some point beforehand.


Just noticed your edit, is wyvern a singleton of your system object? So that backbufferRenderTarget is the same pointer as wyvern.backbufferRenderTarget, only in a different scope (same memory location)? Or is the value of backbufferRenderTarget copied to wyvern.backbufferRenderTarget? (copy constructor of the system object perhaps).

I'll take a wild guess that you're passing the initial instance of your system object into your render function as an argument, or passing it to the render function's parent render object somehow, and that's why it's got an odd function local name like wyvern. The system.cpp destructor gets called when wyvern is destroyed, either when the render function returns, or the render object is destroyed (depending how you passed the system object), and that is when your render target view is actually getting released and destroyed. When the real system object is later destroyed, and the destructor gets called for the second time, the render target view is already released and destroyed by the earlier call to the system.cpp destructor, so you get an exception.

Put a breakpoint in the system.cpp destructor that calls release on the render target view, see how many times it gets hit (my guess is twice, second time the exception happens).

Edited by backstep, 27 October 2013 - 07:16 PM.


#10 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 27 October 2013 - 07:24 PM

 

Sorry about that, I knew I forgot to mention something, backbuffer is a ID3D11RenderTargetView. I have changed it to backbufferRenderTarget.
 
Currently it is only used by the device and device context. It's created and used like in my systems init method like this:
ID3D11Texture2D *pBackbuffer;
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*) &pBackbuffer);
device->CreateRenderTargetView(pBackbuffer, NULL, &backbufferRenderTarget);
pBackbuffer->Release();

deviceContext->OMSetRenderTargets(1, &backbufferRenderTarget, NULL);
The System.CPP is the only portion of the application where it is used and referenced


No worries. smile.png

So far as I know the only way to get an RTV to error on release like that, is to try to release it after it's destroyed. It gains one reference on creation ( device->CreateRenderTargetView(pBackbuffer, NULL, &backbufferRenderTarget); ), are you certain it's not released anywhere else in your code?

Even though release was called on the device and context beforehand, they should still exist, because the device's internal reference counter was incremented when you created the ID3D11RenderTargetView that backbufferRenderTarget points to. Internal reference counters are the same as the external reference counters you call addref and release on, except they're only accessible by other COM objects, rather than external pointers, hence the name internal reference counter. The render target view is a child of the device, and won't decrement the device's internal reference count until it's destroyed.

What that means is I don't think the spritebatcher destructor calls to release the device and context are causing your backbufferRenderTarget->Release() exception. The ID3D11RenderTargetView object is somehow already destroyed, meaning it's external ref count was already 0 at some point beforehand.


Just noticed your edit, is wyvern a singleton of your system object? So that backbufferRenderTarget is the same pointer as wyvern.backbufferRenderTarget, only in a different scope (same memory location)? Or is the value of backbufferRenderTarget copied to wyvern.backbufferRenderTarget? (copy constructor of the system object perhaps).

 

 

I'm not seeing any other portion of the code the where a release is called except in the deconstructor for my System object.

 

wyvern is a singleton of my System object:

//In public area of my Systsme header ffile
ID3D11RenderTargetView  *backbufferRenderTarget;

//In main CPP
System wyvern;

//Used like so
if(wyvern.initSystem(hInstance, winProc, "App Window", false) == false)
		return false;



#11 backstep   Members   -  Reputation: 335

Like
0Likes
Like

Posted 27 October 2013 - 08:03 PM

I'm at a loss, did the breakpoint on the call to backbufferRenderTarget->Release() in the system destructor only get hit once and error on that first call to it?

#12 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 27 October 2013 - 08:53 PM

I'm at a loss, did the breakpoint on the call to backbufferRenderTarget->Release() in the system destructor only get hit once and error on that first call to it?

 

If I use this as my clean up method and variable declares (Not sure If I posted this)

//Variable declares
System wyvern;
SpriteBatcher *batcher;

//Clean up method 
void cleanUp()
{
	if(batcher != NULL)
	{
		delete batcher;
		batcher = NULL;
	}
}

And then have this as my start up / main init method

bool startup(HINSTANCE hInstance, WNDPROC winProc)
{
	if(wyvern.initSystem(hInstance, winProc, "Application Window", false) == false)
		return false;

	return true;
}

The window with the clear color shows and etc. When the window is closed, no break occurs

 

If I have this as my start up / main init method

bool startup(HINSTANCE hInstance, WNDPROC winProc)
{
	if(wyvern.initSystem(hInstance, winProc, "Application Window", false) == false)
		return false;

	batcher = new SpriteBatcher(wyvern.device, wyvern.deviceContext);

	return true;
}

The break occurs in my System.CPP's deconstructor sad.png

/* Other clean up items  in the deconstructor*/

if(backbufferRenderTarget != NULL)
{
	backbufferRenderTarget->Release(); //<--Breaks here
	backbufferRenderTarget = NULL;
}

I just don't understand because I only create / set the render target in the initSystem call

 

Now what I find interesting is that if I do this as my clean up

void cleanUp()
{
	wyvern.~System();

	if(batcher != NULL)
	{
		delete batcher;
		batcher = NULL;
	}
}

My application breaks in the SpriteBatcher.CPP here

SpriteBatcher::~SpriteBatcher()
{
	if(batDevice != NULL)
	{
		batDevice->Release(); <-- Breaks here
		batDevice = NULL;
	}

	if(batDeviceContext != NULL)
	{
		batDeviceContext->Release();
		batDeviceContext = NULL;
	}

        /* Other clean up items */
}

 So does this mean that releasing my device / device context also releases the render target?


Edited by noodleBowl, 27 October 2013 - 09:01 PM.


#13 backstep   Members   -  Reputation: 335

Like
0Likes
Like

Posted 27 October 2013 - 11:25 PM

Ok just to break that down into the three situations, as you presented them:

1. If you never instantiate batcher during startup, it's destructor is never called, so any COM object release calls only happen in the automatic call of the System object destructor and when that's called there are no errors. Exits cleanly.

2. If you do instantiate batcher, and it's destructor is called without first manually calling the system destructor, then there are no errors from the spritebatch destructor. Then, when the system object is destroyed automatically, it's destructor gives an exception when you try to release the backbufferRenderTarget COM object. It looks like the backbufferRenderTarget COM object was destroyed along with the device and context by the spritebatch destructor, despite it having that pointer's external reference from the system instance.

3. If you do the same as in 2. but first manually call the system destructor, then that call to the system destructor gives no errors, but the following automatic spritebatcher destructor will error when it tries to release the id3d11device a second time (since system's destructor already released and destroyed it).

So situation 1 is normal, and how it should work, only the pointers with references to COM objects call release on them, everything is happy. So all you really want is to instantiate batcher while retaining the object management of situation 1, right?

In situation 2, The error is caused by releasing pointers that never addref'd the pointed COM objects (batdevice and batdevcontext). I'm honestly not really certain why it's breaking the way that it does. It should give a runtime warning, but I don't understand why it full on errors on the backbufferRenderTarget. It's to do with the chain of internal references between the device, the swapchain, the ID311Texture2D of the backbuffer, and finally the ID3D11RenderTargetView that errors when you release. I'd expect the open external reference from backbufferRenderTarget would keep all the objects alive in that internal reference chain, but it does not. I don't understand the internal relationships of the DXGI/D3D runtimes well enough to say what exactly is going on. I can say how you'd fix it though, either addref the device and context in the spritebatcher constructor, or never call release on them in the spritebatch destructor.

In situation 3 it's the same problem, you're calling release when you never addref spritebatcher's pointers to the device and context, so in this case those objects no longer exist to call release on (since the manual call of the system destructor released and destroyed them first). So once more, either addref the spritebatcher device and context pointers, or never call release on them, and the problem goes away, but also never manually call the system destructor like that. Even if you fix the problem with spritebatcher, you're in a situation where the system destructor gets called twice, once manually, once automatically, for a single instance of the system. Your checks in the destructor will probably prevent an error, but manually calling destructors is a bad idea in almost all if not absolutely all cases.

I hope it makes sense that the only pointers that call release on a COM object are those which have added an external reference to them. The pointer passed into their creation automatically has it's reference added, so that's the only pointer you really need to call release with. When you create a copy of that pointer, no reference was added automatically, and if you didn't call addref yourself, then why would the copy need to release a reference it never held.

Like I said before, it would be best to consider ownership of the COM objects when you handle pointers to them. You can make it so the pointer that was used in their creation is the sole owner and only this pointer ever calls release on the object. Any other pointers to the same COM object will never call addref or release, only the initial owner pointer will call release once when the object is no longer needed. This is easiest.

A second choice is share ownership of the COM object's between all pointers to them, and to do that make sure every time you copy a COM object pointer that you addref once using the copy, and always call release before that copy goes out of scope or is deleted. This guarantees object lifetime to all pointers but is also more susceptible to mistakes (if you ever forget to addref or release one pointer then the system breaks down, also it's a ton more boilerplate code).

A third choice is to use ComPtr's which will handle calling release and addref for you. They're like smart pointers for COM objects. I personally use ComPtr's to handle ownership, and pass raw pointers when I need to share them, and I never call release or addref on any raw pointers. That's not necessarily advised, but it works for me. This is more complicated to learn, but easiest to use, and if you give up using raw pointers entirely then it guarantees object lifetime just as well as the second choice, but without the risk of mistakes or extra code required.

To be clear I recommend that right now you follow the first choice until you're more comfortable using D3D11 and COM objects. Only look into using ComPtr once you have a handle on how to use COM objects, since ComPtr's have their own wrinkles (assigning by copy, manually releasing them etc) that will only add complication you don't need when starting out.

Edited by backstep, 27 October 2013 - 11:58 PM.


#14 noodleBowl   Members   -  Reputation: 184

Like
0Likes
Like

Posted 28 October 2013 - 07:56 PM

So situation 1 is normal, and how it should work, only the pointers with references to COM objects call release on them, everything is happy. So all you really want is to instantiate batcher while retaining the object management of situation 1, right?

I hope it makes sense that the only pointers that call release on a COM object are those which have added an external reference to them. The pointer passed into their creation automatically has it's reference added, so that's the only pointer you really need to call release with. When you create a copy of that pointer, no reference was added automatically, and if you didn't call addref yourself, then why would the copy need to release a reference it never held.

Like I said before, it would be best to consider ownership of the COM objects when you handle pointers to them. You can make it so the pointer that was used in their creation is the sole owner and only this pointer ever calls release on the object. Any other pointers to the same COM object will never call addref or release, only the initial owner pointer will call release once when the object is no longer needed. This is easiest.
 

 

This to me would be the ideal situtation. I only want my System object to have / retain all ownership of the device and device context  COM objects.

The spritebatcher in my opinion should only have access to the device and device context COM objects, not any type of ownership.

 

The spritebatcher only needs to use those objects to draw stuff to the screen and etc. Also I do not want to create a copies of the device and device context objects. The spritebatcher just needs to know that they exist. Something that I thought I could do with just passing a ref value:

//Spritebatcher.h prototype
SpriteBatcher(ID3D11Device *&device, ID3D11DeviceContext *&deviceContext);

//Spritebatcher.cpp construcotr
SpriteBatcher::SpriteBatcher(ID3D11Device *&device, ID3D11DeviceContext *&deviceContext)
{
    batDevice = device;
    batDeviceContext = deviceContext;

    /*Other constructor code */
}

But I guess this is not the case? How can I make situtation 1 possible?


Edited by noodleBowl, 28 October 2013 - 07:58 PM.


#15 backstep   Members   -  Reputation: 335

Like
0Likes
Like

Posted 28 October 2013 - 08:48 PM

Just change the constructor so you're copying the system device pointer value, rather than currently making a pointer-to-pointer. You'd only be copying the pointers, not the actual COM objects pointed to, it's still only one COM object, that now has two pointers pointing to it.
 
//Spritebatcher.h prototype
SpriteBatcher(ID3D11Device *device, ID3D11DeviceContext *deviceContext);

//Spritebatcher.cpp construcotr
SpriteBatcher::SpriteBatcher(ID3D11Device *device, ID3D11DeviceContext *deviceContext)
{
    batDevice = device;
    batDeviceContext = deviceContext;

    /*Other constructor code */
}
then just pass your original device and deviceContext pointers from your system object into the spritebatcher constructor. Make sure the spritebatcher destructor doesn't release them, since it doesn't own them.

If it helps, you could think of the COM objects like heap allocated memory, usually the pointer that was initialized by the new allocation is the one that calls delete. Even if you copy that pointer, you only call delete once for each new. however many times you copy that pointer, only one pointer to that heap memory will call delete on it.

Oh also, try to make sure the swapchain, device, and context are the last released objects when you shutdown. That way you'll avoid situations like #2 in my previous post where you're relying on their internal references to keep them alive until you release their child objects (textures, views, buffers etc).

Edited by backstep, 28 October 2013 - 08:54 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS