Frage zu Direct3D11
-
dot schrieb:
Gar nicht. Wenn dir die Pointer fehlen solltest du rausfinden wo genau du sie verloren hast.
Live Sampler: 1 Live BlendState: 1 Live DepthStencilState: 1 Live RasterizerState: 1 Live Query: 1
Die fünf Elemente habe ich gar nicht erst angerührt. Das steht exakt gar nichts von meinem Code, der auch nicht viel mehr macht als einen Device zu erzeugen.
Direct3D basiert auf COM, das ist unabhängig von C++. Abgesehen davon musst du auch in C++ dafür sorgen dass Objekte die mit new angelegt wurde wieder deleted werden. Außerdem hindert dich ja niemand dran RAII zu benutzen. COM Objekte wie die von Direct3D eignen sich naturgemäß sogar besonders toll dafür...
Nun einen shared_ptr habe ich schon ausprobiert, jedoch gibt es da Konvertierungsprobleme, wenn eine Funktionen einen Pointer darauf nimmt, weswegen er nicht wirklich dafür geeignet ist. Gibts da noch ein paar Tricks, oder muss ich da wirklich meinen eigenen Smartointer schreiben?
-
Fragerorius schrieb:
Die fünf Elemente habe ich gar nicht erst angerührt.
Nun gut, aber du hast zwangsweise die BackBuffer-Texture angerührt und ein RenderTargetView dafür erzeugt. Der Rest hängt vielleicht damit zusammen.
Fragerorius schrieb:
Gibts da noch ein paar Tricks, oder muss ich da wirklich meinen eigenen Smartointer schreiben?
http://msdn.microsoft.com/en-us/library/ezzw7k98.aspx
http://msdn.microsoft.com/en-us/library/417w8b3b.aspx#ifndef COMPTR_INCLUDED #define COMPTR_INCLUDED #pragma once template <class T> class com_ptr { private: T* ptr; static void release(T* ptr) { if (ptr) ptr->Release(); } static void acquire(T* ptr) { if (ptr) ptr->AddRef(); } public: com_ptr(T* ptr = nullptr) : ptr(ptr) { } com_ptr(const com_ptr& p) : ptr(p.ptr) { acquire(ptr); } com_ptr(com_ptr&& p) : ptr(p.ptr) { p.ptr = nullptr; } ~com_ptr() { release(ptr); } com_ptr& operator =(const com_ptr& p) { acquire(p.ptr); release(ptr); ptr = p.ptr; return *this; } com_ptr& operator =(com_ptr&& p) { std::swap(ptr, p.ptr); return *this; } void release() { release(ptr); ptr = nullptr; } T* operator ->() const { return ptr; } operator T*() const { return ptr; } T** operator &() { return &ptr; } }; #endif // COMPTR_INCLUDED
-
Danke für deine Implementierung der Smartpointers, hat mir wirklich sehr geholfen. Jedoch habe ich ein Problem mit der Swapchain, alle com_ptr werden vernünftig released, nur bei der Swapchain bekomme ich eine Zugriffverletzung, beim releasen, der Pointer ist dabei kein nullptr. Wenn ich nur aus der Swapchain wieder einen normalen Pointer mache, funktioniert mein Programm einwandfrei, woran liegt das?
-
Kann es sein dass die SwapChain irgendwie doppelt released wird? Initialisierst du irgendwo zwei com_ptr mit dem selben IDXGISwapChain*? Denn wenn du einmal einen com_ptr auf ein Objekt erstellt hast solltest du alle weiteren com_ptr auf das selbe Objekt erzeugen indem du den ersten com_ptr kopierst und nicht einen weiteren com_ptr mit dem selben IIrgendwas* erzeugen da der entsprechende Konstruktor kein AddRef() aufruft. Dann passiert nämlich genau dass einmal zu oft Release() aufgerufen wird.
-
Ah ja, ich hab irgendwo versteckt, noch vergessen eine Release zu löschen
Nun habe ich aber alles mit com_ptr gemacht, jedoch sagt mir der Debugger immer noch, dass viele Sachen nicht released wurden. Die Liste ist sogar unverändert geblieben....
-
Zeig vielleicht mal deinen Code her...
-
Hier die Funktion (auf Direct3D gekürzt) die alles erstellt.
Mit dem Device der zurückgegeben wird, wird bis auf initialisieren, überhaupt nichts gemacht.struct Device { Device(com_ptr<IDXGISwapChain> swapchain_, com_ptr<ID3D11Device> dev_, com_ptr<ID3D11DeviceContext> devcon_) : swapchain(swapchain_), dev(dev_), devcon(devcon_), running(running_) {}; com_ptr<IDXGISwapChain> swapchain; com_ptr<ID3D11Device> dev; com_ptr<ID3D11DeviceContext> devcon; }; Device CreateDevice { com_ptr<IDXGISwapChain> swapchain; com_ptr<ID3D11Device> dev; com_ptr<ID3D11DeviceContext> devcon; DXGI_SWAP_CHAIN_DESC sd; std::memset(&sd, 0, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 8; sd.SampleDesc.Quality = 0; sd.Windowed = true; D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT flags = 0; #ifdef DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif if(FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, &sd, &swapchain, &dev, nullptr, &devcon))) { err << "Can't create Direct3D11 device or swapchain" << endl; return failDevice; } // Create a render target view com_ptr<ID3D11Texture2D> backBuffer; if(FAILED(swapchain->GetBuffer( 0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)))) { err << "Can't get the BackBuffer" << endl; return failDevice; } HRESULT hr = dev->CreateRenderTargetView(backBuffer, nullptr, &targetView ); backBuffer->Release(); if(FAILED(hr)) { err << "Can't create RenderTargetView" << endl; return failDevice; } devcon->OMSetRenderTargets(1, &targetView, nullptr); D3D11_VIEWPORT vp; vp.Width = static_cast<float>(width); vp.Height = static_cast<float>(height); vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; devcon->RSSetViewports(1, &vp); return Device(swapchain, dev, devcon); }
-
Warum backBuffer->Release();?
Ist targetView auch ein com_ptr?
-
Hab jetzt mal mit Suchen und ersetzen alle Release() weggemacht.
targetView ist zum testen eine globale Variable, aber auch ein com_ptr.
-
Fragerorius schrieb:
targetView ist zum testen eine globale Variable, aber auch ein com_ptr.
Naja, dann ist klar. Der Destruktor von targetView wird erst aufgerufen nachdem der Device schon freigegeben wurde. targetView ist ein RenderTargetView und hält daher intern noch eine Referenz auf weitere Dinge, wie z.B. den BackBuffer...