Du bist nicht angemeldet.

Werbeanzeige

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

28.11.2015, 22:23

Direct3D 11 | Was passiert da?

Hi,
mir ist gerade etwas aufgefallen und konnte in der MSDN nichts dazu finden (oder habe es übersehen).
Bei mir werden zwei Vertexbuffer mit "IASetVertexBuffer()" gebunden.
Etwa so:

C-/C++-Quelltext

1
2
3
4
5
6
7
// Code...
     pContext->IASetVertexBuffers(&buffer1,...);
     pContext->IASetVertexBuffers(&buffer2,...);
// Code...
     ClearRenderTargetView(); // DX-Methoden
     Draw();
     Present();


Dann stürzt das Program ab, wenn ich buffer1 & buffer2 per "Release()" freigebe. Ich bekomme eine "Access Violation" beim Aufruf von "pBuffer->Release()"; pBuffer ist ein "D3D11Buffer"-Objekt.
Mache ich das jedoch ein wenig anders, etwa so:

C-/C++-Quelltext

1
2
3
4
5
     ClearRenderTargetView();
     pContext->IASetVertexBuffers(&buffer1,...);
     pContext->IASetVertexBuffers(&buffer2,...);
     Draw();
     Present();

Dann stürzt mein Program nicht ab.
Ich kann jetzt leider nicht so ganz nachvollziehen, warum dies passiert.
In der MSDN steht auch nichts brauchbares.

MfG Julien

P.S.: Das "doppelte Binden" kam bei mir durch Denkfehler zustande.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

2

28.11.2015, 23:23

Könntest du mal den Code zeigen, wo du die beiden Buffer's releast?
Und zeig mir bitte den ganzen Code beim ersten IASetVertexBuffers

Ich glaube ich weiss wo du den Fehler gemacht hast, aber ich will mir sicher sein ^^

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

3

28.11.2015, 23:56

Das releasen an sich:

C-/C++-Quelltext

1
2
3
4
5
6
virtual void release(){
                        if(valid){
                            valid = false;
                            pBuffer->Release();
                        }
                    }


Die Objekte werden von der "D3D11::Context" Klasse gesammelt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Context::~Context(){

    for(VertexBuffer*   pBuffer : _VertexBuffers)
         delete pBuffer;

    for(IndexBuffer*    pBuffer : _IndexBuffers)
         delete pBuffer;

    pSwapChain->Release();
    pRTV->Release();
    pDevice->Release();
    pContext->Release();

    // TODO:
    // Keep track of created resources and delete them then.
}


C-/C++-Quelltext

1
2
3
4
5
6
if(_VertexBuffers[buffer_id]->isValid()) // Die Vertexbuffer werden in einem "std::vector" gespeichert.
     pContext->IASetVertexBuffers(0,
     1,
     &(_VertexBuffers[buffer_id]->pBuffer),
     &stride,  // sizeof(float)*7, ja wird noch korrigiert
     &offset); // 0


Aufgerufen wird's dann so:
(int main(){ )

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
46
47
48
49
50
51
52
53
54
55
    Vertex triangle[] =
    {
        {0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
        {0.45f, -0.5, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {-0.45f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f}
    };

    Vertex quad[] =
    {
        {-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
        {0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f},
        {-0.5f, -0.5f, 0.0f, 0.55f, 0.26f, 0.68f, 1.0f}
    };

    unsigned int IndexBuffer[] =
    {
        0, 1, 3,
        1, 2, 3
    };

    try{
        Window  window(L"Direct3D 11", 600, 400);
        Event   event;
        pContext = getContext(&window);

        int buffer = pContext->createVertexBuffer(&triangle, sizeof(Vertex)*3);

        int quadsv = pContext->createVertexBuffer(&quad, sizeof(Vertex) * 4);
        int quadsi = pContext->createIndexBuffer(&IndexBuffer, sizeof(unsigned int) * 6);

        while(event.eventID != Event::EventID::Closed){
            pContext->clearFrame();


            pContext->setVertexBuffer(buffer);
            // pContext->draw(3, 0);

            pContext->setVertexBuffer(quadsv);
            pContext->setIndexBuffer(quadsi);
            pContext->drawIndexed(6, 0, 0);

            pContext->present();
            window.pollEvent(event);
        }

        delete pContext;
    }
    catch(std::runtime_error e){
        std::cout << "An exception has occured!" << std::endl
            << e.what() << std::endl;
    }
    catch(...){
        std::cout << "An unkown exception has occured!" << std::endl;
    }


EDIT:
Ich habe den Code an einigen Stellen umgeschrieben,
u.a weil "std::vector" den Destruktor an Stellen aufgerufen hat,
an denen es unerwünscht war.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

4

28.11.2015, 23:58

Eine Frage.
Wieso verwendest du bei der Release Funktion ein virtual?
Meiner Meinung nach ist dieses unrelevant

Könntest du noch die Stelle zeigen, wo du die Variablen erstellst? (Buffers)

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

5

29.11.2015, 00:05

Zur Zeit ist es tatsächlich unnötig. Das "release" ist Teil der "ResourceBuffer"-Klase, welche von "VertexBuffer" und "IndexBuffer" vererbt wird.
Ich hab's anscheinend versehentlich stehen gelassen :sleeping:
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

6

29.11.2015, 00:09

Bei mir sieht das ganze zum Beispiel so aus:

Der Destruktor ist leer

C-/C++-Quelltext

1
2
3
ModelClass::~ModelClass()
{
}


Dafür habe ich alles in der Shutdown Funktion(bei dir Release Funktion),

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void ModelClass::ShutdownBuffers()
{
    //Release the index buffer
    if (m_indexBuffer)
    {
        m_indexBuffer->Release();
        m_indexBuffer = nullptr;
    }

    //Release the vertex buffer
    if (m_vertexBuffer)
    {
        m_vertexBuffer->Release();
        m_vertexBuffer = nullptr;
    }

    return;
}


Und die rufe ich in einer anderen Klasse auf, die das Programm zum einten Teil erstellt

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
void GraphicsClass::Shutdown()
{
    if (m_D3D)
    {
        m_D3D->Shutdown();
        m_D3D = nullptr;
    }

    return;
}


PS: Sind jetzt zwei unterschiedliche Klasse aber so würde ich das ganze löschen ^^ (Die einte Klasse ist noch in Bearbeitung)

7

29.11.2015, 00:14

Könntest du noch den Code zeigen, wo du die Variablen erstellst?

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

8

29.11.2015, 00:20

Ich glaube, dass das zu umfrangreich wird. Ich habe insgesamt 400 Zeilen Code in dieser einen Datei (abzüglich Headerguards etc.).
Um welche Variablen geht es genau?
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

9

29.11.2015, 00:20

Nur um die Buffers

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

10

29.11.2015, 00:25

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
                    bool create(ID3D11Device*   pDevice,
                                const void* pData,
                                int size)
                    {
                        D3D11_BUFFER_DESC bf_desc = {};
                        bf_desc.Usage           = D3D11_USAGE_DEFAULT;
                        bf_desc.ByteWidth       = size;
                        bf_desc.BindFlags       = D3D11_BIND_VERTEX_BUFFER;
                        bf_desc.CPUAccessFlags  = 0;
                        bf_desc.MiscFlags       = 0;

                        D3D11_SUBRESOURCE_DATA res_data = {};
                        res_data.pSysMem            = pData;
                        res_data.SysMemPitch        = 0;
                        res_data.SysMemSlicePitch   = 0;

                        HRESULT hr = pDevice->CreateBuffer(
                            &bf_desc,
                            &res_data,
                            &pBuffer
                        );

                        valid = SUCCEEDED(hr);
                        return valid;
                    }


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
                int     Context::createVertexBuffer(const void* pData, const int size){
                    VertexBuffer*   pBuffer = new VertexBuffer();
                    if(pBuffer->create(pDevice, pData, size)){
                        _VertexBuffers.push_back(pBuffer);
                        return _VertexBuffers.size() - 1;
                    }
                    else
                        return -1;
                }


Der Unterschied zwischen Vertex-/Indexbuffer ist jetzt nicht groß. Ich werde bei Gelegenheit beiden Funktionen zusammenführen und per Parameter angeben, woran ich binden soll.

Anmerkung:
_VertexBuffer und der Pendat _IndexBuffer sind Container vom Typ "std::vector" die global innerhalb der ".cpp" gespeichert sind.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Werbeanzeige