Proper usage of ComPtr in DirectX code - com

I am writing a DirectX 11 based engine.
Where all of the DirectX Com objects are wrapped in Microsoft::WRL::ComPtr.
But unfortunately when I am calling ID3D11Debug::ReportLiveDeviceObjects on shutdown, it is reporting more the reference count for more than 1 objects are non-zero.
I am confused, which code actually increasing those reference count preventing teh reference to be zero at the end. For an example, I am providing this example usage of ID3D11ShaderResourceView in my code:
The ID3D11ShaderResourceView was declared in my render target class as member,
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_pShaderResourceView
It was initialized in to nullptr in the constructor:
m_pShaderResourceView(wwNULLPTR)
The interface was created as follows:
device->CreateShaderResourceView(m_pDXTexture.Get(), &shaderResourceDesc, m_pShaderResourceView.ReleaseAndGetAddressOf());
The interface was used in GenerateMips function:
deviceContext->GenerateMips(m_pShaderResourceView.Get());
There is a getter function for the interface:
ID3D11ShaderResourceView* GetShaderResourceView()
{
return m_pShaderResourceView.Get();
}
and at last the interface was reset in desctructor:
m_pShaderResourceView.Reset();
At the end I am getting at least 8 reference in live object summary.
My questions are:
Which part of my code is actually increasing the reference count?
Why calling Reset is not making the reference zero?
Probably I am missing something?
Thanks.

ID3D11Debug::ReportLiveDeviceObjects is a very useful debugging tool, but it does have some quirks. Specifically a few objects have lives you don't directly control and are part of the ID3D11Device itself. You can't get rid of the references without closing the device, at which point you can't get a live objects report.
In the DXUT for Direct3D 11 framework, I get it down as much as possible by calling ClearState and then Flush on the immediate context just before calling report live objects.
Even in a 'clean' exit you will still have a few lingering "live" objects:
D3D11 WARNING: Live ID3D11Device at 0x025CA03C, Refcount: 5 [ STATE_CREATION WARNING #441: LIVE_DEVICE]
D3D11 WARNING: Live ID3D11Context at 0x02831030, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #2097226: LIVE_CONTEXT]
D3D11 WARNING: Live ID3DDeviceContextState at 0x02828038, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #3145742: LIVE_DEVICECONTEXTSTATE]
D3D11 WARNING: Live ID3D11BlendState at 0x005B766C, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #435: LIVE_BLENDSTATE]
D3D11 WARNING: Live ID3D11DepthStencilState at 0x0283ECAC, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #436: LIVE_DEPTHSTENCILSTATE]
D3D11 WARNING: Live ID3D11RasterizerState at 0x027006F4, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #437: LIVE_RASTERIZERSTATE]
D3D11 WARNING: Live ID3D11Sampler at 0x0270082C, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #434: LIVE_SAMPLER]
D3D11 WARNING: Live ID3D11Query at 0x005BB904, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #438: LIVE_QUERY]
D3D11 WARNING: Live ID3D11Context : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3DDeviceContextState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3D11BlendState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3D11DepthStencilState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3D11RasterizerState : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3D11Sampler : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
D3D11 WARNING: Live ID3D11Query : 1 [ STATE_CREATION WARNING #422: LIVE_OBJECT_SUMMARY]
These are the 'default' objects used by the runtime itself. Ideally the debug runtime would ignore them when generating this report, but it doesn't.
That said, as you have 8 instead of 5 live objects, you may have something lingering on. First try the ClearState and Flush to make sure you aren't having anything kept alive by the virtue of being bound to the pipeline or due to deferred destruction. If there are still objects left, the next step in finding them is to make use of "Debug Object Naming" so you can figure out what objects you control are still alive. The debug naming can be done using either a macro or a template:
Template
template<UINT TNameLength>
inline void SetDebugObjectName(_In_ ID3D11DeviceChild* resource, _In_z_ const char (&name)[TNameLength])
{
#if defined(_DEBUG)
resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name);
#else
UNREFERENCED_PARAMETER(resource);
UNREFERENCED_PARAMETER(name);
#endif
}
Macro
#ifdef _DEBUG
inline void DXUT_SetDebugName( _In_ ID3D11DeviceChild* pObj,
_In_z_ const CHAR* pstrName )
{
if ( pObj )
pObj->SetPrivateData( WKPDID_D3DDebugObjectName,
(UINT)strlen(pstrName), pstrName );
}
#else
#define DXUT_SetDebugName( pObj, pstrName )
#endif
You need to link to dxguid.lib to get the symbol WKPDID_D3DDebugObjectName. "WKPDID" stands for Well Known Private Data ID. It's ironic since it isn't all that 'well known'.
See Object Naming and Direct3D SDK Debug Layer Tricks

Related

Error using Accelstepper library in PlatformIO mbed

I have successfully instantiated my accelstepper objects:
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(AccelStepper::DRIVER, ZSTEP, ZDIR);
//Create accelstepper object for the theta axis actuator
AccelStepper taxis(AccelStepper::DRIVER, TSTEP, TDIR);
//Create accelstepper object for the magnet actuator
AccelStepper maxis(AccelStepper::DRIVER, MSTEP, MDIR);
Now I am trying to do some basic setup with these objects:
void stepper_setup(){
//Set Max Speed in steps per second
zaxis.setMaxSpeed(100);
taxis.setMaxSpeed(100);
maxis.setMaxSpeed(100);
//Set Acceleration in steps per second squared
zaxis.setAcceleration(500);
taxis.setAcceleration(500);
maxis.setAcceleration(500);
//Home the Zaxis, Taxis, Maxis
zaxis.moveTo(100000); taxis.moveTo(100000); maxis.moveTo(100000);
zaxis.run(); taxis.run(); maxis.run();
However, the compiler throws me the following error:
.pio\build\nucleo_f410rb\lib799\libAccelStepper.a(AccelStepper.o): In function `AccelStepper::runSpeed()':
c:\Users\USER\Documents\PROJECTFOLDER\Codes\PROJECT TITLE/.pio\libdeps\nucleo_f410rb\AccelStepper/AccelStepper.cpp:63: undefined reference to `t'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nucleo_f410rb\firmware.elf] Error 1
and when look up the problematic line 63 in AccelStepper.cpp in question, i can only find this line:
_currentPos -= 1;
This is the picture of the problematic line and
This is the picture of the error thrown in the compiler
which doesn't make sense. Am I missing something? Any help would be greatly appreciated!

DirectX11 COM object with 0 references not released

I'm trying to track down a "memory leak." However it's doesn't seem like a real memory leak since calling ReportLiveDeviceObjects reports that there are 0 references
D3D11 WARNING: Live ID3D11Texture2D at 0x00000140D3FE44F0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D]
D3D11 WARNING: Live ID3D11RenderTargetView at 0x00000140D3FCBB60, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #428: LIVE_RENDERTARGETVIEW]
D3D11 WARNING: Live ID3D11Texture2D at 0x00000140D3FE5BF0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #425: LIVE_TEXTURE2D]
D3D11 WARNING: Live ID3D11RenderTargetView at 0x00000140B8EDB000, Refcount: 0, IntRef: 0 [ STATE_CREATION WARNING #428: LIVE_RENDERTARGETVIEW]
As you can see, the ID3D11RenderTargetView objects have both 0 internal and external references. However it's still a live object. What could cause this to happen?
For clarity, I am using this through SharpDX, though that shouldn't affect the debug output from DirectX 11.
Corresponding issue:
https://github.com/sharpdx/SharpDX/issues/903
DirectX 11 uses 'deferred destruction' of resources, so typically if you need to force destruction you need to Flush. For example, in Direct3D game templates, you need to fully unbind and destroy the render targets before resizing:
// Remove any bound render target or depth/stencil buffer
ID3D11RenderTargetView* nullViews [] = { nullptr };
m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr);
// Destroy the views (which themselves hold the references to the resources)
m_renderTargetView.Reset();
m_depthStencilView.Reset();
// Flush the immediate context to force cleanup
m_d3dContext->Flush();

SFML sf::RenderWindow::createWindow() crashes program

So I've been learning C++ and I've been trying to learn some SFML 2 via some videos. At first I had no real issues, I was using MS VS2012 and everything was fine. I start using MS VS2015 Community and it all starts going wrong and I've got no idea why!
Main problem:
Everything compiles, but it just crashes when I try to use sf::RenderWindow::createWindow()
Error Message:
I get the message "SFML_Project.exe is no longer working",
I go to debug it and it gives me the following message:
Unhandled exception thrown: read access violation.
this->_Ptr was 0xCCCCCCCC.
If there is a handler for this exception, the program may be safely continued.
and it does it on this function (some SFML code I know nothing about)
const facet *_Getfacet(size_t _Id) const
{ // look up a facet in locale object
const facet *_Facptr = _Id < _Ptr->_Facetcount
? _Ptr->_Facetvec[_Id] : 0; // null if id off end <- ON THIS LINE OF CODE IT BREAKS
if (_Facptr != 0 || !_Ptr->_Xparent)
return (_Facptr); // found facet or not transparent
else
{ // look in current locale
locale::_Locimp *_Ptr = _Getgloballocale();
return (_Id < _Ptr->_Facetcount
? _Ptr->_Facetvec[_Id] // get from current locale
: 0); // no entry in current locale
}
}
Line of info that was given at the Call Stack
sfml-system-d-2.dll!std::locale::_Getfacet(unsigned int _Id) Line 451 C++
My Code:
#include <iostream>
#include "SFML\Graphics.hpp"
int main()
{
sf::RenderWindow window;
window.create(sf::VideoMode(800, 800), "WindowName");
sf::Texture texture;
sf::Sprite sprite;
texture.loadFromFile("Player.png");
sprite.setTexture(texture);
sf::Event eventHandler;
while(window.isOpen())
{
while(window.pollEvent(eventHandler))
{
switch(eventHandler.type)
{
case sf::Event::Closed:
window.close();
break;
}
}
window.clear();
window.draw(sprite);
window.display();
}
}
SFML version: Visual C++ 14 (2015) - 32-bit
Project Properties:
Debug -> C/C++ -> General -> Additional Include Directories:
$(SolutionDir)/SFML-2.3.2/include
Debug -> Linker -> General -> Additional Library Directories:
$(SolutionDir)/SFML-2.3.2/lib
Debug -> Linker -> Input -> Additional Dependencies:
sfml-main-d.lib
sfml-window-d.lib
sfml-graphics-d.lib
sfml-system-d.lib
sfml-network-d.lib
sfml-audio-d.lib
What I've tried:
I've tried turning all the dependencies from sfml-XX-d.lib to sfml-XX.lib files, which does allow me to create a window and draw shapes to that window, but then when I try to use sf::Texture::loadFromFile("filename") the console command window turns into the matrix and starts beeping.
It might be because you link the window lib before the graphics lib.
Try to move up the window lib under the graphics lib.
sfml-graphics-d.lib
sfml-window-d.lib
sfml-system-d.lib
If it's still crashing, it may because your sfml's dlls does not match the current sfml version that you have. Happened to me once, I downloaded a new version of sfml without updating the binaries.

Second call to CoCreateInstance creates Application object again

I have a COM component with two CoClasses.
IMyApp is my application CoClass interface.
IFunction is my second ColClass interface.
For the first time when i Create IMyApp object using CoCreateInstance and followed with IFunction object using CoCreateInstance, everything works fine.
Problem:
Now again when i try to Create object of IFunction using CoCreateInstance it calls initinstance of my main application IMyApp.
Following is my IDL file library content:
library DemoPrjLib
{
Importlib("stdole2.tlb");
[
uuid(661CAC63-8F13-473B-8857-48233A668029),
helpstring("MyApp Class")
]
coclass MyApp
{
[default] interface IMyApp;
};
[
uuid(104A759B-1088-435C-A2F3-7F5FD13C233A),
helpstring("Function Class")
]
coclass Function
{
[default] interface IFunction;
};
};
// Creating Application object first time with success
::CoCreateInstanceEx(_uuidof(MyApp), 0, CLSCTX_ALL, &oServerInfo, 1, multi_qi);
// Now creating object of IFunction
CComPtr<IFunction> pFunction;
HRESULT hr = pFunction.CoCreateInstance (CLSID_Function); // this goes sucessfully
if (pFunction)
{
AfxMessageBox ("Works fine!!!");
}
if (pFunction)
pFunction.Release ();
// Problem Here: below call creates MyApp instance again i.e. it calls initinstance of my COM Application
hr = pFunction.CoCreateInstance (CLSID_Function);
Any suggestion is really appreciated.

Why does DTrace give me invalid-address errors sometimes but not always?

My program:
typedef struct objc_class {
struct objc_class *isa;
struct objc_class *super_class;
char *name;
long version;
long info;
long instance_size;
void *ivars;
void *methodLists;
void *cache;
void *protocols;
} *Class;
struct objc_object {
Class isa;
};
/* Code to extract the class name from arg0 based on a snippet by Bill Bumgarner: http://friday.com/bbum/2008/01/26/objective-c-printing-class-name-from-dtrace/ */
objc$target:NSObject:-init:entry {
printf("time: %llu\n", timestamp);
printf("arg0: %p\n", arg0);
obj = (struct objc_object *)copyin(arg0, sizeof(struct objc_object));
printf("obj: %p\n", obj);
printf("obj->isa: %p\n", obj->isa);
isa = (Class)copyin((user_addr_t)obj->isa, sizeof(struct objc_class));
printf("isa: %p\n", obj->isa);
classname = copyinstr((user_addr_t)(isa->name));
printf("classname: %s\n", classname);
}
Some output:
dtrace: script 'test.d' matched 1 probe
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28
CPU ID FUNCTION:NAME
0 61630 -init:entry time: 28391086668386
arg0: 1291ae10
obj: 6f0a1158
obj->isa: a023f360
isa: a023f360
classname: NSBitmapImageRep
1 61630 -init:entry time: 28391586872297
arg0: 12943560
obj: 6f4a1158
obj->isa: 2fca0
isa: 2fca0
classname: GrowlApplicationTicket
1 61630 -init:entry time: 28391586897807
arg0: 152060
obj: 6f4a1280
obj->isa: 2fe20
isa: 2fe20
classname: GrowlNotificationTicket
2 61630 -init:entry time: 28391079142905
arg0: 129482d0
obj: 700a1128
obj->isa: a0014140
isa: a0014140
classname: NSDistributedObjectsStatistics
2 61630 -init:entry time: 28391079252640
arg0: 147840
obj: 700a1250
obj->isa: a0014780
isa: a0014780
classname: NSDistantObjectTableEntry
Why the errors? It seems to be the class name (that's the only %s, and I don't get any errors if I remove it), but why does it think some classes' names are invalid pointers?
Is there any way to get the error messages to actually tell me which line of my DTrace program caused a problem?
Is there a way to call object_getClassName instead of doing this structure-inspection dance?
For what it's worth, the program I'm tracing works fineā€”it's not crashing, so I don't believe that the classes really are broken.
Colin is pretty close to correct.
See:
http://www.friday.com/bbum/2008/01/03/objective-c-using-dtrace-to-trace-messages-to-nil/
More likely than not, you need to set the DYLD_SHARED_REGION environment variable to avoid. dtrace only really works against mapped memory that is actually resident in physical memory.
You can figure out what is missing by using the vmmap command line tool.
Do a vmmap PID on your application after the above failure messages are generated. Looking at the output, see what region the addresses like 0x90206b98 fall into. Given that address, it is likely in a non-writeable shared chunk of memory that probably isn't resident and, thus, dtrace can't read from it.
This error happens when copyin / copyinstr is used on a page that's not faulted in yet. A common workaround is to let the function use the data in question, and then copyin[str] in a :::return clause. For example:
syscall::open:entry
{
self->filename = arg0; /* Hang on to the file name pointer. */
}
syscall::open:return
/self->filename/
{
#files[copyinstr(self->filename)] = count();
self->filename = 0;
}
END
{
trunc(#files, 5);
}
I haven't entirely tracked this down myself. It's possible that DTrace is trying to resolve some Objective-C symbols. Although DTrace is a dynamic tracing facility it doesn't mesh well with Objective-C dynamically loading things at runtime. When Objective-C does load new classes,etc DTrace has to resolve this and it takes a little time, especially when your app is just starting up. Even if it does get things loaded, and your objc app is still loading new classes onto the objc runtime its possible DTrace could get screwed up and print methods in the wrong order (if you care about seeing the correct order methods are being executed in), print incorrect timing results,etc.
This is my best guess based on the information provided.
DTrace was purposefully designed in such a way as to make DTrace scripts as deterministic as possible. This is why there are no if statements, loops, subroutines (other than the pseudo-subroutines provided by DTrace itself), etc. This is because the code in your DTrace script is running in kernel mode, not user-land as part of the process(es) being traced. In general, the information DTrace has access to is "read-only" (like most generalizations, this is not strictly true), being able to twiddle bits in programs, or the kernel, with something as powerful as DTrace can cause things to go very, very wrong, very very quickly.
Dollars to donuts, the problem you're having is because the page that the pointer points to is not mapped in to core by the VM system. DTrace can only examine information for memory that is in core- it can't double-fault to get the VM system to load in the page.
You can probably help alleviate the problem if you've got an idea of what the classes "should" be and forcing the pages to be mapped in to core by doing a bunch of dummy NSLog() statements that reference the needed classes at some convenient point early in your programs start up.