Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Ashnarott

Frischling

  • »Ashnarott« ist der Autor dieses Themas

Beiträge: 57

Beruf: Student Maschinenbau

  • Private Nachricht senden

1

10.12.2010, 14:46

ID3D10Texture2D in ID3D11Texture2D konvertieren?

Hi ich habe ein Problem und zwar möchte ich mit D3D11 gerne Text und 2D Objekte rendern.
Eigentlich sollte dies dank Direct2D ja kein Problem sein, aber das läuft nur mit DirectX10 und DirectX10.1! DirectX11 bleibt da außen vor und Microsoft scheint laut mehreren Foren keine Lust zu haben dieses Problem in nächster Zeit zu beheben.
Jetzt wollte ich das ganze über DirectX11 in verbindung mit DirectX10 lösen.
Ich benutze DirectX11 zum rendern in den Backbuffer. DirectX10 wird einfach initialisiert und renderd in eine ID3D10Texture2D (Hauptsächlich Text mit ID3DX10Font).
Jetzt habe ich mich gefragt ob es möglich ist die ID3D10Texture2D in eine ID3D11Texture2D zu konvertieren? Ich würde dann die Textur über die Szene legen und somit wieder ID3DX10Font nutzen können. Außerdem könnte ich dann mein GUI - Framework, welches ich für DX10 programmiert habe weiter nutzen und müsste nicht alles für D3D11 umschreiben!

Ich habe schon versucht die Texturen über ID3D10Texture2D::Map() und ID3D11DeviceContext::Map() zu sperren, um die Texel von der D3D10 Textur in die D3D11 Textur zu kopieren. Leider hat man nach meinem Wissen keine Möglichkeit Lesezugriff auf die D3D10 Textur zu erhalten, da sie ein RenderTarget ist.
Auch habe ich versucht ID3D10Resource in ID3D11Resource zu konvertieren, das ist mir auch nicht gelungen und ich habe nichts dazu gefunden.

Ich habe schon ewig nach einer Lösung im Internet gesucht aber leider nichts gefunden. Ich hoffe ihr könnt mir weiterhelfen ;)
Danke schonmal :)
Traue einem Computer, aber niemals seinen Programmierer!!!

BlazeX

Alter Hase

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

2

10.12.2010, 16:49

Ja, das geht mit Shared Resources und Keyed Mutex.
Im Prinzip erstelle ich mit D3D10.1 eine Texture2D, fordere ein Shared-Interface an und "öffne" mit D3D11 das Shared-Resource-Interface als Texture2D-Interface.
Danach werden noch für beide Interfaces so genannte Mutexes angefordert. Mit denen muss vor jedem Benutzen der Resource die Resource gesperrt und hinterher wieder entsperrt werden.
Ich habe das gemacht, als es noch keinen D3D11-Renderer für die CEGUI gab. Damals gab es nur einen D3D10-Renderer.
Hier ist das wichtigste aus dem Code:

Variablen:

C-/C++-Quelltext

1
2
3
4
5
6
//GUI BackBuffer
ID3D10Device1 * pD3D10Device;   //Das D3D10-Device für die GUI
ID3D10Texture2D * pGUIBuffer10; //Das D3D10-Interface des BackBuffer
ID3D11Texture2D * pGUIBuffer11; //Das D3D11-Interface des BackBuffer    
ID3D10RenderTargetView * pGUIRTV10; //Das RenderTarget der GUI
ID3D11ShaderResourceView * pGUISRV11;   //Das von der GUI gerenderte Bild nutzen


Init:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//Direct3D10Device für die GUI erstellen
        D3D10CreateDevice1(pVideo->GetAdapter(),
            D3D10_DRIVER_TYPE_HARDWARE,
            NULL,
            0,
            D3D10_FEATURE_LEVEL_10_0,
            D3D10_1_SDK_VERSION,
            &pD3D10Device);

        //BackBuffer (D3D10) erstellen
        D3D10_TEXTURE2D_DESC BufferTextureDesc;
        BufferTextureDesc.Width         = VideoSettings.dwBBSizeX;
        BufferTextureDesc.Height            = VideoSettings.dwBBSizeY;
        BufferTextureDesc.Format            = DXGI_FORMAT_R8G8B8A8_UNORM;
        BufferTextureDesc.MipLevels         = 1;
        BufferTextureDesc.ArraySize         = 1;
        BufferTextureDesc.SampleDesc.Count  = 1;
        BufferTextureDesc.SampleDesc.Quality= 0;
        BufferTextureDesc.Usage             = D3D10_USAGE_DEFAULT;
        BufferTextureDesc.BindFlags         = D3D10_BIND_RENDER_TARGET|D3D10_BIND_SHADER_RESOURCE;
        BufferTextureDesc.CPUAccessFlags    = 0;
        BufferTextureDesc.MiscFlags         = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
        TRY_DX(pD3D10Device->CreateTexture2D(&BufferTextureDesc, NULL, &pGUIBuffer10));
    
        //BackBuffer (D3D11) teilen
        IDXGIResource * pBackBufferResource;
        TRY_DX(pGUIBuffer10->QueryInterface(__uuidof(IDXGIResource*), (void**)(&pBackBufferResource)));
        HANDLE hSharedBackBuffer= NULL;
        TRY_DX(pBackBufferResource->GetSharedHandle(&hSharedBackBuffer));
        ID3D11Resource * pBackBufferSharedResource;
        TRY_DX(pD3D11Device->OpenSharedResource(hSharedBackBuffer, __uuidof(ID3D11Resource*), (void**)(&pBackBufferSharedResource)));
        TRY_DX(pBackBufferSharedResource->QueryInterface(__uuidof(ID3D11Texture2D*), (void**)(&pGUIBuffer11)));
        pBackBufferSharedResource->Release();

        //RTV und SRV erstellen
        TRY_DX(pD3D10Device->CreateRenderTargetView(pGUIBuffer10, NULL, &pGUIRTV10));
        TRY_DX(pD3D11Device->CreateShaderResourceView(pGUIBuffer11, NULL, &pGUISRV11));

        //Keyed Mutexes anfordern
        TRY_DX(pGUIBuffer10->QueryInterface(_uuidof(IDXGIKeyedMutex*), (void**)(&pMutex10)));
        TRY_DX(pGUIBuffer11->QueryInterface(_uuidof(IDXGIKeyedMutex*), (void**)(&pMutex11)));


Rendern:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//////////////////////////////////////////////////////////////////
        //Direct in den BackBuffer rendern
        Video::VideoDevice * pVideo= Video::VideoDevice::Instance();
        ID3D11DeviceContext * pDC= pVideo->GetImmediateDeviceContext();

        ID3D11Resource * pBackBuffer;
        pVideo->GetBackBufferRTV()->GetResource(&pBackBuffer);

        //BackBuffer in den GUIBuffer kopieren
        pMutex11->AcquireSync(0, INFINITE);
        pDC->CopyResource(pGUIBuffer11, pBackBuffer);
        pMutex11->ReleaseSync(0);

        //GUI rendern
        pMutex10->AcquireSync(0, INFINITE);
        pD3D10Device->OMSetRenderTargets(1, &pGUIRTV10, NULL);

        CEGUI::System::getSingleton().renderGUI(); //Hier wird in den BackBuffer gerendert. Im BackBuffer ist das Bild der Szene. Jetzt kommt die GUI oben drauf.

        pMutex10->ReleaseSync(0);

        //GUIBuffer zurück in den BackBuffer kopieren
        pMutex11->AcquireSync(0, INFINITE);
        pDC->CopyResource(pBackBuffer, pGUIBuffer11);
        pMutex11->ReleaseSync(0);

        pBackBuffer->Release();

Ashnarott

Frischling

  • »Ashnarott« ist der Autor dieses Themas

Beiträge: 57

Beruf: Student Maschinenbau

  • Private Nachricht senden

3

10.12.2010, 17:35

Hi, also schon mal vielen vielen Dank für die schnelle Antwort! Ich habe gleich versucht den Code umzusetzen

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    //Variablen
    HRESULT             hResult;
    db_sConfig*         pConfig                 =   dbGetConfig();
    UINT                uiCreateDeviceFlags     =   0;

#ifdef DB_DEBUG
    //Wenn DEBUG - Modus aktiv ist DEBUG Direct3D - Device erstellen...
    uiCreateDeviceFlags |=  D3D10_CREATE_DEVICE_DEBUG;
#endif

    //Information ausgeben...
    DB_INFO("Initialisiere Direct3D10.1...");

    //Direct3D10 - Schnittstelle initialisieren...
    hResult = D3D10CreateDevice1(NULL, (D3D10_DRIVER_TYPE)(pConfig->Direct3D.mDriverType), NULL, uiCreateDeviceFlags, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, &this->m_pD3D10Device1);
    
    //Überprüfen ob die erstellung Fehlgeschlagen ist, wenn ja dann DirectX10 probieren...
    if(FAILED(hResult))
    {
        //Information ausgeben...
        DB_INFO("Fehler beim initialisieren von Direct3D10.1. Probiere Direct3D10 zu initialisieren!");

        //Direct3D10 - Schnittstelle initialisieren...
        DB_ERROR_DIRECTX(D3D10CreateDevice1(NULL, (D3D10_DRIVER_TYPE)(pConfig->Direct3D.mDriverType), NULL, uiCreateDeviceFlags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &this->m_pD3D10Device1), "D3D10CreateDevice1:D3D10_FEATURE_LEVEL_10_0", DB_ERROR);
    }

    //Information ausgeben...
    DB_INFO("Direct3D10.1 wurde erfolgreich initialisiert");;

    //Backbuffer definieren...
    D3D10_TEXTURE2D_DESC    mD3D10BufferDesc;
    mD3D10BufferDesc.Width              =   pConfig->Direct3D.uiWidth;
    mD3D10BufferDesc.Height             =   pConfig->Direct3D.uiHeight;
    mD3D10BufferDesc.Format             =   DXGI_FORMAT_R8G8B8A8_UNORM;
    mD3D10BufferDesc.MipLevels          =   1;
    mD3D10BufferDesc.ArraySize          =   1;
    mD3D10BufferDesc.SampleDesc.Count   =   pConfig->Direct3D.uiMultiSampleCount;
    mD3D10BufferDesc.SampleDesc.Quality =   pConfig->Direct3D.uiMultiSampleQuality;
    mD3D10BufferDesc.Usage              =   D3D10_USAGE_DEFAULT;
    mD3D10BufferDesc.BindFlags          =   D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
    mD3D10BufferDesc.CPUAccessFlags     =   0;
    mD3D10BufferDesc.MiscFlags          =   D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;

    //Backbuffer erstellen... (HIER KOMMT E_INVALIDARG)
    DB_ERROR_DIRECTX(m_pD3D10Device1->CreateTexture2D(&mD3D10BufferDesc, NULL, &m_pD3D10BackBuffer), "m_pD3D10Device1->CreateTexture2D():m_pD3D10BackBuffer", DB_ERROR);


Leider bringt er mir bei CreateTexture2D "E_INVALIDARG". Es liegt auf jedenfall nicht an SampleDesc, das habe ich bereits überprüft.
Traue einem Computer, aber niemals seinen Programmierer!!!

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Ashnarott« (10.12.2010, 17:50)


BlazeX

Alter Hase

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

4

10.12.2010, 20:28

Ich glaube Shared Resources dürfen nicht multisampled sein.
Das Problem kannst du aber speicheraufendig lösen: 1 Multisampled Texture2D als RenterTarget, 1 nicht multisampled Texture2D als Shared Resource. Mit der Funktion ResolveSubresource kannst du das MS-RenderTarget in die Shared Resource runtersampeln.

Alternativ kannst du dir eine 2. Texture2D als Staging Resource erstellen. Den BackBuffer kopierst du dir in die Staging Resource, mappst sie zum Lesen. Deine dynamische D3D11 Texture mappst du zum Schreiben. Und dann einfache Speicherkopie.
Von dieser Alternative würde ich aber abraten, da umständlich über die CPU kopiert wird. Das geht mächtig auf die Bandbreite (Ein multisampled BackBuffer ist ganz schön groß) und drückt deine FPS ins bodenlose.

Eine 1. Alternative wäre nicht ID3DX10Font zu benutzen. Nimm zum Beispiel die CEGUI. (Warnung vorweg: Das SDK ist Mist, lad dir wenn schon den Source und die Depencies runter und kompilier das Ding neu, vergiss nicht die Effect11 DLLs aus dem DX-SDK neu zu kompilieren, die aus den CEGUI-Deps sind irgendwie schrottig.)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlazeX« (10.12.2010, 20:34)


Ashnarott

Frischling

  • »Ashnarott« ist der Autor dieses Themas

Beiträge: 57

Beruf: Student Maschinenbau

  • Private Nachricht senden

5

10.12.2010, 21:32

Funktioniert der Code bei dir?
Multisampling muss ja nicht unbedingt sein, ich denke aber das der Fehler woanders liegt.
Und ich möchte es jetzt erst nochmal mit DirectX 10 versuchen, da ich dafür schon ein komplettes GUI geschrieben habe, aber danke für den Tipp ;)

Ich hab nochmal richtig debuggt und raus bekommen das es anscheinden was mit dem IDXGI zu tun:

D3D10: ERROR: ID3D10Device::CreateTexture2D: D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX is only available for devices created off of Dxgi1.1 factories or later

Muss ich bei D3D10CreateDevice1() vieleicht einen Adapter angeben?
Hab schon versucht einen auszulesen, allerdings kenn ich mich damit NULL aus, da ich immer D3D10CreateDevice1(NULL,... ) angegeben hab.

C-/C++-Quelltext

1
2
3
4
5
   //Factory erstellen...
DB_ERROR_DIRECTX(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory)), "CreateDXGIFactor1():pFactory", DB_ERROR);

//Adapter abfragen...
DB_ERROR_DIRECTX(pFactory->EnumAdapters1(0, &pDeviceAdapter), "pFactory->EnumAdapters1()", DB_ERROR);


Erzeuge ich jetzt mit dem Adapter über D3D10CreateDevice1(pDeviceAdapter,...) stürzt das Programm allerdings da schon ab mit "E_INVALIDCALL"
Ich weiß das ich hier nur den ersten Adapter an der Stelle "0" auslese. Ich hab dann die Beschreibung von diesem abgefragt und es ist meine Grafikkarte, kapier also nicht warum das jetzt plötzlich hier schon abstürzt.

Ich hoffe das hilft weiter :P
mfg

Edit (11-12-2010) 13:00
@BlazeX:
Ich hab mich mal durch dein Tutorial für die Adapter geackert. Musste nur D3D_DRIVER_TYPE_UNKNOWN angeben. Jetzt stürzt er allerdings bei OpenSharedResources ab. Ich melde mich, wenn ich weiterkommen.
Traue einem Computer, aber niemals seinen Programmierer!!!

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Ashnarott« (11.12.2010, 13:10)


Ashnarott

Frischling

  • »Ashnarott« ist der Autor dieses Themas

Beiträge: 57

Beruf: Student Maschinenbau

  • Private Nachricht senden

6

11.12.2010, 13:35

Also es funktioniert. Hatte jetzt vergessen Multisampling wieder auf 0 zu setzen :D
Vielen dank für die Hilfe!!!!!!!!

mfg,

Ashnarott
Traue einem Computer, aber niemals seinen Programmierer!!!

Werbeanzeige