|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 27.02.2008, 16:27 Titel: Device Reset schlägt fehl bei Rendertarget |
|
|
Die Überschrift drückts recht gut aus.
Es klappt alles ohne Probleme, aber sobald ich ein Rendertarget erstelle (ich muss das nicht mal per SetRendertarget setzen), bekomme ich von der Reset()-Methode des D3D9-Devices ein unbarmherziges "D3DERR_INVALIDCALL".
Ich gebe alle Texturen (egal ob managed oder nicht) vor dem Reset frei.
So erstelle ich das Target:
CPP: | //*******************************************************************
//[[[ Rendertarget erstellen ]]]
//*******************************************************************
cDevice->CreateTexture(Width,Height,1,D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&new_sprite.sTexture,NULL); |
Größe und Format sind dieselben wie bei den PresentationParameters für den Backbuffer angegeben. Diese übergebe ich natürlich beim Reset()-Aufruf mit.
Irgendwelche Ideen, woran es liegen könnte? _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 27.02.2008, 17:49 Titel: |
|
|
Wenn CreateTexture erfolgreich verläuft aber Reset() fehlschlägt dann musst du noch irgendwo eine Referenz auf deine Textur halten, aktiviere die DX Deebug Runtime und beachte das Outputfenster deiner IDE, dort sollte stehen was genau da Probleme macht. |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 28.02.2008, 01:06 Titel: |
|
|
Danke, hab die Debug Runtime eigentlich noch nie so wirklich verwendet, aber hab jetzt gleich mal einen Heap-Memoryleak feststellen können.
Dummer Fehler von mir.
Ich hab fürs Erstellen des Indexbuffers einen Zeiger erstellt, der auf NULL zeigt, den für den Buffer angegeben, gesperrt und per Indexoperator hineingeschrieben. Ich weiß auch nicht mehr, wo ich mir das abgeschaut hab und wieso das bisher geklappt hat...
Jedenfalls hab ich das jetzt als Array definiert und nicht als einfachen Zeiger ins Leere laufen lassen.
So, nun aber noch eine Frage: Beim direkten Reinschreiben scheints ja so Probleme zu geben, aber (wieso) gibt es die nicht, wenn man per memcpy in den Buffer kopiert?
Beispiele:
Geht nicht:
CPP: | short* index_data;
//Create Indexbuffer
//Buffer fürs Schreiben locken
sIndexbuffer->Lock(0,0,(void**)&index_data,0);
//Daten(Indizies) schreiben
index_data[0]=0;
index_data[1]=1;
index_data[2]=2;
index_data[3]=3;
//Unlocken |
Wieso geht das hier? So wirds nämlich auch im Buch gemacht.
Hier wird auch kein Speicher für den letztendlichen Zielbuffer reserviert.
Seh ich richtig, dass das schlechter Stil ist bzw, auch zu Leaks/Problemen führen kann?
CPP: | short* index_data;
short index_data_array[4];
//Daten(Indizies) schreiben
index_data_array[0]=0;
index_data_array[1]=1;
index_data_array[2]=2;
index_data_array[3]=3;
//Create Indexbuffer
//Buffer fürs Schreiben locken
sIndexbuffer->Lock(0,0,(void**)&index_data,0);
//Daten kopieren
memcpy(index_data,index_data_array,sizeof(index_data_array));
//Unlocken |
_________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 28.02.2008, 06:42 Titel: |
|
|
Sollte der IndexBufferArray nicht vom Typ WORD anstatt vom Typ short sein? Zumidest mache ich es so und es funktioniert. |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 28.02.2008, 16:32 Titel: |
|
|
Haben doch beide 2 Bytes. KA, ob WORD da richtiger ist. Es funktioniert ja jetzt auch mit short.
Nur meine Frage war, wieso man memcpy einfach auf einen Zeiger anwenden kann, der irgendwo in den Speicher zeigt.
Dass es knallen kann, wenn man per Indexoperator drauf zugreift, ist mir klar. Aber ich verstehe/weiß nicht, was da memcpy anders macht. _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 28.02.2008, 17:45 Titel: |
|
|
kann es sein das deine Indexdaten read-only sind? Laut DX-Doc führt sowas zu undefiniertem verhalten, da das ja direkt auf der graka ist und die keine guardians hat...
Gruß DXer |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 28.02.2008, 18:50 Titel: |
|
|
DirectXer hat Folgendes geschrieben: | kann es sein das deine Indexdaten read-only sind? Laut DX-Doc führt sowas zu undefiniertem verhalten, da das ja direkt auf der graka ist und die keine guardians hat...
Gruß DXer |
Wenn Readonly der Standardwert (0) ist, sind sie das wohl. Spielt aber auch keine Rolle, es gibt ja keine Probleme/Leaks mehr.
Ich finds nur verwirrend - deshalb die Frage - wieso memcpy da so einfach rankommt, ohne Speicher zu reservieren (was ja mit dem Indexoperator anstatt memcpy Probleme bereiten kann). _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 28.02.2008, 20:44 Titel: |
|
|
The Lord of Programming hat Folgendes geschrieben: | DirectXer hat Folgendes geschrieben: | kann es sein das deine Indexdaten read-only sind? Laut DX-Doc führt sowas zu undefiniertem verhalten, da das ja direkt auf der graka ist und die keine guardians hat...
Gruß DXer |
Wenn Readonly der Standardwert (0) ist, sind sie das wohl. Spielt aber auch keine Rolle, es gibt ja keine Probleme/Leaks mehr.
Ich finds nur verwirrend - deshalb die Frage - wieso memcpy da so einfach rankommt, ohne Speicher zu reservieren (was ja mit dem Indexoperator anstatt memcpy Probleme bereiten kann). |
naja memcpy arbeitet mit pointern und unsigned 8-bit, nicht mit arrays und 16-bit, aber eigentlich dürfte das keinen unterschied machen... wo gibts denn genau den fehler? beim ersten [0]? probier vllt auch mal mit 8-bit-pointern zu arbeiten?
Gruß DXer |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 28.02.2008, 21:39 Titel: |
|
|
DirectXer hat Folgendes geschrieben: | wo gibts denn genau den fehler? beim ersten [0]? |
Es tritt nicht mal immer auf. Ich konnte meistens ein paar Indexbuffer erstellen, bis er irgendwann deswegen gemeckert hat. Ich vermute, der wird einfach meckern, wenn die Stelle im Speicher [arrayanfang+arraygröße] schon von irgendwas anderes allokiert wurde.
Nehm ich nur den Zeiger "short* indices;" her, wer sagt mir, dass 4 Stellen weiter im Speicher immer noch nichts ist? Ich könnt ja theoretisch auch mit dem Index 9999 zuzugreifen versuchen.
Dasselbe wäre per memcpy im Prinzip auch möglich, wenn ich ein 1000-er Array erstelle und das per memcpy an die betreffende Stelle im Speicher kopiere.
Unsigned 8-bit? Aber Vertexbuffer und Indexbuffer haben doch eine feste Größe für die Einzelwerte. Mit 8 Bit könnten Indexbuffer ja maximal 256 verschiedene Indizes enthalten. _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 02.03.2008, 11:52 Titel: |
|
|
The Lord of Programming hat Folgendes geschrieben: | Unsigned 8-bit? Aber Vertexbuffer und Indexbuffer haben doch eine feste Größe für die Einzelwerte. Mit 8 Bit könnten Indexbuffer ja maximal 256 verschiedene Indizes enthalten. |
Nein ich meine memcpy, dem übergibst du unsigned char* und die Größe in Bytes (kann auch char* sein, ist hier egal). Ist ja dasselbe hier, wird eben nur byte für byte kopiert, nicht 16-bitweise. Im Grunde ist das aber zweirangig....
Aber der Fehler tritt nur auf, wenn du dem Wert etwas versuchst zuzuweisen oder? memcpy greift ja nur lesend darauf zu, das würde das dann erklären. Dann spricht das vielleicht wirklich für read-only.
Gruß DXer |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 02.03.2008, 14:42 Titel: |
|
|
Also jetzt bin ich verwirrt...
DirectXer hat Folgendes geschrieben: | Nein ich meine memcpy, dem übergibst du unsigned char* und die Größe in Bytes (kann auch char* sein, ist hier egal). Ist ja dasselbe hier, wird eben nur byte für byte kopiert, nicht 16-bitweise. Im Grunde ist das aber zweirangig.... |
Ja...ich übergebe memcpy schlichtweg die Form, in der es vorliegt. D.h. für den Vertexbuffer ein Array mit einer Struktur und für den Indexbuffer ein short-Array. Dürfte eigentlich ziemlich egal sein, da memcpy sowieso immer auf die gleiche Weise kopiert.
DirectXer hat Folgendes geschrieben: | Aber der Fehler tritt nur auf, wenn du dem Wert etwas versuchst zuzuweisen oder? memcpy greift ja nur lesend darauf zu, das würde das dann erklären. Dann spricht das vielleicht wirklich für read-only. |
Memcpy greift auf den zweiten Parameter lesend zu(const void *src) und auf den ersten schreibend(void *dest). Insofern verstehe ich nicht, was da anders sein soll.
Das Ziel bleibt ja das gleiche, ob ich memcpy nehme oder den Indexoperator.
CPP: | short* index_data;
memcpy(index_data,index_data_array,sizeof(index_data_array));
//oder:
index_data[0]=0;
//[...] |
Die Quelle ist halt einmal ein ganzes Array, das byteweise Kopiert wird und das andere Mal ein einzelner Wert. Aber da sehe ich nicht das Problem(die Quelle ist ja im Speicher schon reserviert)...eher am Ziel.
Erstelle ich einen Zeiger, der einfach ins nichts läuft, wie kann das gut gehen, wenn ich da schreibend darauf zugreife?
Ist es nicht auch schlechter Stil, Zeiger uninitialisiert zu lassen? _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 03.03.2008, 19:58 Titel: |
|
|
The Lord of Programming hat Folgendes geschrieben: | DirectXer hat Folgendes geschrieben: | Aber der Fehler tritt nur auf, wenn du dem Wert etwas versuchst zuzuweisen oder? memcpy greift ja nur lesend darauf zu, das würde das dann erklären. Dann spricht das vielleicht wirklich für read-only. |
Memcpy greift auf den zweiten Parameter lesend zu(const void *src) und auf den ersten schreibend(void *dest). Insofern verstehe ich nicht, was da anders sein soll. |
ahja jetzt seh ichs, ich hab das falsch interpretiert mit memcpy. ich dachte du kopierst nur die werte von der stelle in ein array von dir, d.h. du greifst nur lesen auf den buffer zu; war aber nicht so..
The Lord of Programming hat Folgendes geschrieben: | Die Quelle ist halt einmal ein ganzes Array, das byteweise Kopiert wird und das andere Mal ein einzelner Wert. Aber da sehe ich nicht das Problem(die Quelle ist ja im Speicher schon reserviert)...eher am Ziel. |
hmm das macht eigentlich keinen unterschied, es sei denn memcpy ist irgendwie anders implementiert(normalerweise wird memcpy mit __asm{movsb} implementiert...), aber du kannst das ganz einfach testen indem du dir mal ein eigenes memcpy schreibst wo du die werte ganz normal zuweist. Dann kannst du testen, was dabei geht und was nicht....
The Lord of Programming hat Folgendes geschrieben: | Erstelle ich einen Zeiger, der einfach ins nichts läuft, wie kann das gut gehen, wenn ich da schreibend darauf zugreife?
Ist es nicht auch schlechter Stil, Zeiger uninitialisiert zu lassen? |
Ohja das ist ein seehhr schlechter stil, im buch schreibt christian einen ganzen abstatz voller warnungen um jeden neuen programmierer davon abzuschrecken Also generell solltest du Zeiger _immer_ mit 0 oder einem anderen gültigen wert initialisieren; sonst kannst im allerschlimmsten fall zu hohem datenverlust führen. Am einfachsten ist, wenn du dir eine smart pointer klasse für normale pointer schreibst die im Konstruktor der pointer mit 0 initialisiert, aber das ist schon wieder etwas anderes.
Gruß DXer |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 04.03.2008, 12:20 Titel: |
|
|
Gut, jetzt kommen wir der Sache schon näher
Wäre es also das beste und sauberste, wenn ich anstatt einem "Leerzeiger" einfach ein Array mit entsprechender Größe reserviere?
CPP: | short* index_data=new short [sizeof(index_data_array)/sizeof(index_data_array[0])];
memcpy(index_data,index_data_array,sizeof(index_data_array));
//Buffer fürs Schreiben locken
sIndexbuffer->Lock(0,0,(void**)&index_data,0);
//Daten kopieren
memcpy(index_data,index_data_array,sizeof(index_data_array));
//Unlocken
delete[] index_data; |
Nun aber noch ne Frage: Muss ich dann den Speicherbereich solange reserviert lassen wie der Indexbuffer nutzbar sein soll oder hat LPDIRECT3DINDEXBUFFER9 nach dem Erstellen per CreateIndexBuffer() schon einen eigenen Speicherbereich? (Nach dem Namen wohl eher nicht...) _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 04.03.2008, 13:26 Titel: |
|
|
Der Speicherbereich sollte sich dann ja auf der Grafikkarte befinden. Da du per C++/Windows normalerweise kein Speicher auf der Grafikkarte reservieren kannst, sollte man den Speicher sicher löschen können.
Den Vertex/Index buffer sind ja gerade deshalb so schnell, weil sich alle Daten schon auf der Garfikkarte befinden. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 04.03.2008, 14:57 Titel: |
|
|
Der code da würde ein größeres mem-leak verursachen, da Lock() eine Pointervariable erwartet und diese auf den index buffer setzt dein mit new allokiertes Array würde einfach fallen gelassen, und delete unten hat noch andere schlimmere folgen
Also nochmal komplett in Schritten, wie das mit index buffern ist:
- Du rufst CreateIndexBuffer auf und übergibst unter anderem die Größe der zukünftigen index-daten in byte; diese Funktion reserviert dann den Speicher in deinem indexbuffer-objekt (norm. auf der graka)
- Du erstellst einen ganz normalen short* pointer (oder long, je nachdem was du bei Create...() übergeben hast; standard ist short) und initialisierst ihn mit null. Von Lock() wird dieser auf den von Create...() reservierten Speicher gesetzt
- Du rufst Lock() auf und übergibst diesen Pointer, Lock setzt diesen nun wie gesagt auf den Speicher (die index-daten)
- Du kopierst entweder mit memcpy die Indices über diesen Pointer in den Speicher oder setzt sie selber mit dem array-index-operator. Du musst hier nur darauf achten, dass du nicht höher greifst als du bei Create...() angegeben hast, da dir der Speicher dadrüber nicht mehr gehört
- Du rufst Unlock() auf und sagst DX somit, dass du mit bearbeiten fertig bist.
Das ganze jetzt mal in Code: CPP: | // index buffer für 4 short indices reservieren und in <ib> speichern
device->CreateIndexBuffer( 4 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, 0 );
// pointer anlegen
short* pInds = 0;
// pointer holen
ib->Lock( 0, 0, reinterpret_cast<void**>(&pInds), 0 );
// daten schreiben (nur von [0] bis [3]!)
pInds[0] = 0;
...
pInds[3] = 2;
// DX sagen, dass wir fertig sind
ib->Unlock(); |
Hoffe, dass jetzt alles klar iss (mal eine ganz vage vermutung weshalb das ganze: kann es sein dass du bei create() einfach das sizeof(short) weggelassen hast? das passiert nämlich öfter mal )
Gruß DXer |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|