Rendu dans une texture,Pourquoi ça foire une fois sur 2 ? [C++ / D3D8] - Programmation
Marsh Posté le 22-01-2002 à 14:44:18
en fait, c lors de l'appel à la fonction :
"lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, NbIndex, NbVertices, 0, NbIndex/3)"
que ça plante la plupart du temps (je l'ai vu grâce au débug dans un fichier, en fait la fonction ne retourne même pas d'erreur, elle plante tout simplement...). Bizarrement ça ne plante pas systématiquement, parfois le plugin peut se lancer une ou deux fois, ensuite il plante toujours à cette fonction, parfois aussi le rendu visuel est corrompu...
Pendant un moment j'ai cru que les cartes non pourvu de T&L ne pouvait pas rendre des sommets non transformé dans une texture (ce qui explique la portion de code qui réalise les transformation uniquement si le T&L est detecté, de même sans T&L le format des sommets n'est pas le même: ce sont des sommets transformés), mais finalement ce n'est pas ça... alors quelle peut-être la raison ???
je vous en prie aidez-moi je galère depuis bien trop longtemps avec ce foutu D3D8 ... (je trouve ça mal foutu qu'une fonction plante plutôt que de retourner un message d'erreur) et je sens que je vais péter les plombs
je rappelle que ça marche nickel avec des cartes récentes (apparement qui dispose du T&L mais j'en suis pas sur).
Vous pouvez m'aider aussi en testant vous-même le plug-in chez vous et en me disant ce que contient le fichier debug si ça plante (un ficher nommé "debug_nebula.txt" qui a la facheuse habitude d'être n'importe où sur le dur après exécution du plugin). Pour tester le plugin vous devez télécharger les fichiers:
http://scalpel.multimania.com/down [...] nebula.dll (environ 700 Ko .. hum..)
http://scalpel.multimania.com/down [...] /flare.bmp
(1,30 Ko )
et les mettre dans le rep /winamp/plugins (ou /winamp3/plugins poour ceux qui utilisent Winamp3).
Merci d'avance !!
[edtdd]--Message édité par ZZZzzz--[/edtdd]
Marsh Posté le 22-01-2002 à 14:51:25
bah installe les DLL debug de DX8 pis regarde si elle te dit qqchose...
Marsh Posté le 22-01-2002 à 15:12:12
chrisbk a écrit a écrit : bah installe les DLL debug de DX8 pis regarde si elle te dit qqchose... |
pareil.
et je crois bien que faire un SetRenderTarget() fait un AddRef() sur la surface. donc si tu ne fais pas un Release() derrière tu risques peut-être qq problèmes ... et je croyais qu'on ne pouvais faire de SetRenderTarget() qu'avec deux surfaces compatibles (chacune ayant color/zbuffer ou color seulement).
sinon, c'est aussi peut-être (sûrement) un problème de drivers à chier.
Marsh Posté le 22-01-2002 à 16:03:55
ZZZzzz a écrit a écrit : je vous en prie aidez-moi je galère depuis bien trop longtemps avec ce foutu D3D8 ... (je trouve ça mal foutu qu'une fonction plante plutôt que de retourner un message d'erreur) et je sens que je vais péter les plombs |
Au contraire D3D8 est plutot bien fichu et ne plante
que si tu as mal fait les choses:
Donc conseils habituels:
- verifie les Devcaps specifiques a ton hardware, Tous ne sont pas capables de rendre dans une texture (G200 pour n'en citer qu'une). Tous les hardware ne supportent pas les textures superieures a 16 bits. Tous ne supportent pas les pointsprites etc.. etc..
- verifies les valeurs de retour de TOUS tes appels DirectX
Exemple si un lock a echoue et que derriere tu essaies d'ecrire dans le pointeur => plantage.
- Installes les debug runtime et execute ton appli dans ton debugueur (sous visual C++ => F5). Si tu as regle la verbosite au maximum, tu auras droit a de jolis warnings si tu fais des choses incorrectes et parfois meme des conseils de performance.
- sinon dans ton programme les conseils de deboguages
habituels initialise tous tes pointeurs a NULL, n'ecris pas
au dela des limites d'un bloc memoire etc..
A+
LEGREG
Marsh Posté le 22-01-2002 à 20:32:18
youdon'tcare> tu as raison pour le AddRef, mais d'après le SDK tu n'sa pas besoin de faire le Release car le Device e fait lui-même:
"The device will call AddRef on each non-NULL surface passed to SetRenderTarget. After that the device calls Release on the previously set color buffer"
sinon j'ai toujours pensé que les drivers NVidia étaient un peu à chier dans le sens où ils plantaient facilement (pendant un moment je collectionnais les écrans-bleus avec mon plug-in, et pourtant ej suis sous XP... à mon avis des drivers correctement foutus ne doivent pas faire d'écrans bleues) .. peut-ête les développeurs des drivers enlèvent qq tests dans un souci de perfs...
legreg> j'ai déjà fait exactement tout ce que tu me conseilles (excepté l'installation des dll de debug)... par contre je vois pas trop comment faire marche le debug pour un fichier DLL (surtout qu'un plugin winamp ne se lance pas automatiquement avec winamp), et comment règle -t-on le degé de verbose ?
c marrant que tu me parle de point sprite car mon plugin les utilise aussi (et à vrai dire là par contre je n'ai pas tester qu'ils soient supporté mais ça ne devrais pas causer de plantages puisque je teste toujours les retours de fonctoins)
bon j'install ces dll de debuging et je vous dis quoi, merci beaucoup en tout cas !
[edtdd]--Message édité par ZZZzzz--[/edtdd]
Marsh Posté le 22-01-2002 à 22:04:50
bon avec le debugging voilà l'erreur que j'obtiens (uniquement lorsque j'initialise le Device D3D avec "D3DCREATE_SOFTWARE_VERTEXPROCESSING" ou "D3DCREATE_MIXED_VERTEXPROCESSING" (ce qui explique que ça marche bien avec les carte bénéficiant du T&L):
avec D3DCREATE_SOFTWARE_VERTEXPROCESSING:
"Direct3D8: (ERROR) :Invalid index in the index stream: 0
Direct3D8: (ERROR) :*** Exception in d:\builds\nt32_chk\multimedia\directx\dxg\d3d8\fe\d3dbase.cpp Line: 3530
Direct3D8: (ERROR) rawIndexedPrimitive failed."
avec D3DCREATE_MIXED_VERTEXPROCESSING:
"Direct3D8: (ERROR) :*** Exception in d:\builds\nt32_chk\multimedia\directx\dxg\d3d8\fe\vshader.cpp Line: 668
Direct3D8: (ERROR) :Streams do not have required number of vertices
Direct3D8: (ERROR) rawIndexedPrimitive failed."
je comprend pas... mon index me semble bien initialisé (et ça fonctionne bien lorsque j'initialise en mode HARDWARE_VERTEX_PROCESSING ??) alors ?? cela signifierait-il que le T&L supporterait l'erreur sans rien dire mais en soft ça passe pas ??? Donc j'aurai bien une erreur dans mon tableau d'index ...
pour ceux qui ont le courage de s'y pencher, voici lafonction d'initialisation du tableau d'indices:
NbVertices contient le nombre de sommets du vertex buffer de vertex et NbIndex le nombre d'index du vertex buffer d'indices
"
// allocation:
NbVertices = (StepMesh)*(StepMeshY);
NbIndex = (StepMesh-1)*(StepMeshY-1)*2*3;
// ... pis on appelle CreateVertexBuffer avec ces valeurs
// ... on initialise le vertex buffers de somets
// puis celui d'indices:
// 0 2 5
// | / |
// définition les index dans l'ordre suivant: 1 3--4
WORD* indices;
if( (d3dval = lpD3DIndexBuf->Lock(0, 0,(BYTE**)&indices,0)) != D3D_OK) {
strcat(D3DErrorMessage, "Cannot Lock IndexBuffer ! <- " );
return d3dval;
}
int stepmeshy = StepMeshY - 1, stepmehsx = StepMesh - 1;
for(j = 0; j < stepmeshy; j++) {
for(i = 0; i < stepmehsx*6; i += 6) {
indices[j*stepmehsx*6 + i] = j*(StepMesh) + i/6;
indices[j*stepmehsx*6 + i + 1] = (j+1)*(StepMesh) + i/6;
indices[j*stepmehsx*6 + i + 2] = j*(StepMesh) + i/6 + 1;
indices[j*stepmehsx*6 + i + 3] = (j+1)*(StepMesh) + i/6;
indices[j*stepmehsx*6 + i + 4] = (j+1)*(StepMesh) + i/6 + 1;
indices[j*stepmehsx*6 + i + 5] = j*(StepMesh) + i/6 + 1;
}
}
lpD3DIndexBuf->Unlock();"
[edtdd]--Message édité par ZZZzzz--[/edtdd]
Marsh Posté le 23-01-2002 à 02:07:28
ya quoi pour la creation du vertex et index buffer?
ou fais-tu ton drawindexedprimitives (vu que c'est la que ca plante)?
As-tu essaye sur des primitives simples?
LEGREG
Marsh Posté le 23-01-2002 à 10:09:15
pour le drawindexedprimitive c dans mon premier copier/coller (en haut du topic), sinon voici comment je crée mon tableau d'index et de vertex:
" NbVertices = (StepMesh)*(StepMeshY);
NbIndex = (StepMesh-1)*(StepMeshY-1)*2*3;
int flags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
int vf = D3DFVF_MYPLANEVERTEX_NOT_TL;
int sizevstruc = sizeof(my_plane_vertex_not_tl);
if(!UseTL) {
flags |= D3DUSAGE_SOFTWAREPROCESSING;
vf = D3DFVF_MYPLANEVERTEX_TL;
sizevstruc = sizeof(my_plane_vertex_tl);
}
// on crée nos buffers de vertex d'abord car ce sont des ressources non "managées"
if( (d3dval = lpD3DDevice->CreateVertexBuffer(NbVertices*sizevstruc,
flags, vf, D3DPOOL_DEFAULT, &lpD3DVertexBuf)) != D3D_OK) {
strcat(D3DErrorMessage, "Cannot Create Vertex Buffer 1 ! <- " );
return d3dval;
}
// .... initialisation
flags = 0;
if(!UseTL) flags |= D3DUSAGE_SOFTWAREPROCESSING;
#ifdef NDEBUG
flags |= D3DUSAGE_WRITEONLY;
#endif
// maintenant on crée le buffer d'indices
if( (d3dval = lpD3DDevice->CreateIndexBuffer(NbIndex*sizeof(WORD),
flags, D3DFMT_INDEX16,
D3DPOOL_DEFAULT, // on peut mettre en MANAGES car ne bouge plus une fois initialisée
&lpD3DIndexBuf)) != D3D_OK) {
strcat(D3DErrorMessage, "Cannot Create IndexBuffer ! <- " );
return d3dval;
}"
ce qui m'étonnes c que ça marche si j'ai initialisé le D3D Device avec le flag HARDWARE_VERTEXPROCESSING (autrement dit si le T&L hardware est activé)... une idée ??
Marsh Posté le 23-01-2002 à 11:13:00
Compare:
DrawIndexedPrimitive(D3DPT_TRIANGLELIST, NbIndex, NbVertices, 0, NbIndex/3)
à
HRESULT DrawIndexedPrimitive(
D3DPRIMITIVETYPE Type,
UINT MinIndex,
UINT NumVertices,
UINT StartIndex,
UINT PrimitiveCount
);
NBIndex c'est ton MinIndex?
(le plus petit indice utilise?)
Par ailleurs, tu n'as pas besoin de preciser
D3DUSAGE_SOFTWAREPROCESSING
Sauf si tu comptes faire un ProcessVertices
ou tu comptes utiliser des fonctions de Vertex programmables
non supportees par ton hardware.
En fait il n'est utile qu'en mode mixed (dans les cas precites), en software il est implicite et en hardware il est illegal.
Pour ton indexbuffer je pense qu'il vaut effectivement mieux le mettre en managed.
A+
LEGREG
Marsh Posté le 23-01-2002 à 14:50:36
merci legreg pour les infos, d'après le SDK:
"Type
[in] Member of the D3DPRIMITIVETYPE enumerated type, describing the type of primitive to render. See Remarks.
MinIndex
[in] Minimum vertex index for vertices used during this call.
NumVertices
[in] The number of vertices indexed during this call, starting from BaseVertexIndex + StartIndex
StartIndex
[in] Location in the index array to start reading indices.
PrimitiveCount
[in] Number of primitives to render. The number of vertices used is a function of the primitive count and the primitive type. The maximum number of primitives allowed is determined by checking the MaxPrimitiveCount member of the D3DCAPS8 structure"
j'avais mal compris le "minindex", je pensais que cété le nombre minimum d'indices utilisé durant l'appel (faut dire que je suis pas trop doué en anglais aussi). ça me semblait bizarre aussi... bon ben je pense que tu as trouvé le pb. C marrant de voir comment les bugs les plus cons sont toujours les plus chiants à trouver... merci beaucoup ! j'essaie la modif de suite !
Marsh Posté le 23-01-2002 à 15:19:34
cété bien ça apparement (incroyable d'être bête à ce point là ...) !! merci encore !
Marsh Posté le 22-01-2002 à 14:39:56
je n'y comprend rien, cela fait maintenant plusieurs jours que je me prend la tête sue un problème: j'ai écrit un plugin winamp qui réalise des effets 2D/3D, et pour cela je dois rendre dans une texture. Le plugin marche très bien sur ma machine (WinXP/GForce DDR/Céléron) et sur les machines disposant de GForce en général (GForce 2MX/GForce3/etc...). Par contre avec une carte plus vielle, soit ça marche pas du tout tou simplement parce-que la carte ne support pas le rendu dans une texture (comme les Ati Rage Pro), dans ce cas l'initialisation du programme foire, soit ça plante aléatoirement lorsque je fais le rendu dans une texture. J'ai tout essay, et à chaque fois ya des plantages....
voici la fonction en question:
"// rendu de la texture source sur la texture destination
// retourne D3D_OK si succes, sinon met à jour D3DErrorMessage
int RenderSourceTextureToDestinationTexture(LPDIRECT3DTEXTURE8 lpD3DTSrc, LPDIRECT3DTEXTURE8 lpD3DTDest) {
HRESULT d3dval = 0;
LPDIRECT3DSURFACE8 lpD3DSSurf = NULL;
strcpy(D3DErrorMessage, "" );
#ifdef _DEBUG
fwrite("/RenderSrcTextoDestText-", 1, strlen("/RenderSrcTextoDestText-" ), (FILE*)debugfile);
#endif
// on récupère d'abord la surface associée à la texture
if( (d3dval = lpD3DTDest->GetSurfaceLevel(0, &lpD3DSSurf)) != D3D_OK) {
strcat(D3DErrorMessage, "Get Surface Level 0 Failed from Destination Texture <- " );
return d3dval;
}
// et on fait le set render target
if( (d3dval = lpD3DDevice->SetRenderTarget(lpD3DSSurf, NULL)) != D3D_OK) {
strcat(D3DErrorMessage, "Set Render Target on Dest Texture Failed <- " );
return d3dval;
}
#ifdef _DEBUG
fwrite("1-", 1, strlen("1-" ), (FILE*)debugfile);
#endif
// activation de la texture source pour le rendu
if( (d3dval = lpD3DDevice->SetTexture(0, lpD3DTSrc)) != D3D_OK) {
strcat(D3DErrorMessage, "SetTexture (stage 0) to lpD3DTSrc Failed <- " );
return d3dval;
}
// on active les indices juste avant le rendu
if( (d3dval = lpD3DDevice->SetIndices(lpD3DIndexBuf, 0)) != D3D_OK) {
strcat(D3DErrorMessage, "Set lpD3DIndexBuf Indices Failed <- " );
return d3dval;
}
int vf = D3DFVF_MYPLANEVERTEX_NOT_TL;
int sizevstruc = sizeof(my_plane_vertex_not_tl);
if(!UseTL) {
vf = D3DFVF_MYPLANEVERTEX_TL;
sizevstruc = sizeof(my_plane_vertex_tl);
}
if( (d3dval = lpD3DDevice->SetStreamSource(0, lpD3DVertexBuf, sizevstruc)) != D3D_OK) {
strcat(D3DErrorMessage, "Set lpD3DVertexBuf Stream Source Failed <- " );
return d3dval;
}
// est-il nécessaire de le refaire à chaque fois ? j'en doute...
if( (d3dval = lpD3DDevice->SetVertexShader(vf)) != D3D_OK) {
strcat(D3DErrorMessage, "Cannot Set Vertex Shader on our vertex format ! <-" );
return d3dval;
}
// et on active la déformation courante
if(UseTL) {
D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
mat *= ScalingMat;
mat *= RotationMat;
mat *= TranslationMat;
if( (d3dval = lpD3DDevice->SetTransform(D3DTS_WORLD, &mat)) != D3D_OK) {
strcat(D3DErrorMessage, "Set Transform on WORLD Failed ! <- " );
return d3dval;
}
}
#ifdef _DEBUG
fwrite("2-", 1, strlen("2-" ), (FILE*)debugfile);
#endif
// et enfin le rendu dans la texture destination !!
/*lpD3DDevice->BeginScene();
if( (d3dval = lpD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, NbIndex, NbVertices, 0, NbIndex/3)) != D3D_OK) {
strcat(D3DErrorMessage, "DrawIndexedPrimitive for screen failed <- " );
return d3dval;
}
lpD3DDevice->EndScene();*/
// une fois la surface utilisée il faut la libérer
if(lpD3DSSurf) { lpD3DSSurf->Release(); lpD3DSSurf = NULL; }
#ifdef _DEBUG
fwrite("RenderSrcTextoDestText\\", 1, strlen("RenderSrcTextoDestText\\" ), (FILE*)debugfile);
#endif
return D3D_OK;
}
"