IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

DirectX Discussion :

[DirectX 10] Utiliser dans le shader une texture créée de toutes pièces.


Sujet :

DirectX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 3
    Par défaut [DirectX 10] Utiliser dans le shader une texture créée de toutes pièces.
    Bonjour,

    Je viens vous demander de l’aide car je me sens coincé dans une situation des plus paradoxales.
    Dans le cadre de la création de distance maps, je dois lire les données d’une texture 2D et calculer ensuite les distances que je stock dans une texture 3D.

    Je passerais sur les difficultés que j’ai eut à lire les données d’une texture puis à en créer une. Le système de texture de directX10 est des plus étranges.

    La situation est donc la suivante : Je dois passer ma ID3D10Texture3D au shader. Il me faut donc la convertir en ID3D10ShaderResourceView. Cette conversion n’est pas des plus complexes, s’il n’y avait ce paradoxe :
    Pour pouvoir utiliser la fonction CreateShaderResourceView, il me faut avoir créé la texture avec le BindFlag D3D10_BIND_SHADER_RESOURCE. Or cette texture a été créé sans aucun BindFlag, sinon, je n’aurais pu agir dessus avec le CPU.
    Je me retrouve donc dans cette situation pour le moins étrange où je ne peux passer au shader une texture que j’ai créé à moins de l’avoir créé de telle sorte que je ne puisse la modifier.

    Voici le code


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    D3DX10_IMAGE_LOAD_INFO loadInfo;
    loadInfo.Width = D3DX10_DEFAULT;
    loadInfo.Height = D3DX10_DEFAULT;
    loadInfo.Depth = D3DX10_DEFAULT;
    loadInfo.FirstMipLevel = D3DX10_DEFAULT;
    loadInfo.MipLevels = D3DX10_DEFAULT;
    loadInfo.BindFlags = 0;
    loadInfo.MiscFlags = D3DX10_DEFAULT;
    loadInfo.Filter = D3DX10_FILTER_NONE;
    loadInfo.MipFilter = D3DX10_FILTER_NONE;
    loadInfo.CpuAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE; //Ces deux flags sont nécessaires. On ne peut pas lire si on ne peut pas écrire.
    loadInfo.pSrcInfo = NULL;
    loadInfo.Usage = D3D10_USAGE_STAGING; //Donne les droits en lecture et écriture sur la resource
     
    ID3D10Texture2D *pTexture2D = NULL;
    ID3D10Resource *pTexture = NULL;
    hr = D3DX10CreateTextureFromFile( g_pd3dDevice, fileName, &loadInfo, NULL, &pTexture, NULL );
    if( FAILED( hr ) )
    	return false;
     
    pTexture->QueryInterface(__uuidof(ID3D10Texture2D),(LPVOID*)&pTexture2D); //conversion de la resource en texture2D
    pTexture->Release();
     
    D3D10_MAPPED_TEXTURE2D mappedTex;
    D3D10_TEXTURE2D_DESC desc;
    pTexture2D->GetDesc(&desc);
    hr = pTexture2D->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_READ_WRITE, 0, &mappedTex );
     
    if( FAILED( hr ) )
    	return false;
    //On se ménage un accès aux données de la texture
    UCHAR* pTexels = (UCHAR*)mappedTex.pData;
     
    //Puis on créé la texture 3D qui va bien.
    int maxDepth = 15;
    ID3D10Texture3D *distMap;
    D3D10_TEXTURE3D_DESC createInfo; //Il faut attribuer à la texture 3D les meme caractéristiques qu'à la texture 2D
    createInfo.Width = desc.Width;
    createInfo.Height = desc.Height;
    createInfo.Depth = maxDepth;
    createInfo.MipLevels = desc.MipLevels;
    createInfo.Format = desc.Format;
    createInfo.Usage = desc.Usage;
    createInfo.BindFlags = 0; //Je ne peux pas mettre le BindFlag au shader ici non plus.
    createInfo.CPUAccessFlags = desc.CPUAccessFlags; //J'utilise ici les meme paramètres que pour la texture2D.
    createInfo.MiscFlags = desc.MiscFlags;
    hr = g_pd3dDevice->CreateTexture3D(&createInfo, NULL, &distMap); //On créé la texture3D
     
    if( FAILED( hr ) )
    	MessageBox(NULL, "Echec de la creation de la texture 3D", "Error", MB_OK);
     
    D3D10_MAPPED_TEXTURE3D mappedDistMap;
    hr = distMap->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_READ_WRITE, 0, &mappedDistMap);
     
    if( FAILED( hr ) )
    	MessageBox(NULL, "Echec du mappage de la texture 3D", "Error", MB_OK);
     
    UCHAR* p3DTexels = (UCHAR*)mappedDistMap.pData;
     
    for(unsigned int curZ=0; curZ < (unsigned int)maxDepth; curZ++)
    {
    	for(unsigned int curY=0; curY < desc.Height; curY++)
    	{
    		for(unsigned int curX=0; curX < desc.Width; curX++)
    		{
    			p3DTexels[curZ*desc.Height*desc.Width*4+curY*desc.Width*4+curX*4] = 255;  //Ici j'attribue des valeurs arbitraires pour pouvoir vérifier
    			p3DTexels[curZ*desc.Height*desc.Width*4+curY*desc.Width*4+curX*4+1] = 255;//que ma texture peut etre remplie par mes soins et que
    			p3DTexels[curZ*desc.Height*desc.Width*4+curY*desc.Width*4+curX*4+2] = 255;//le shader affiche les informations ensuite.
    			p3DTexels[curZ*desc.Height*desc.Width*4+curY*desc.Width*4+curX*4+3] = 255;
    		}
    	}
    }
     
    D3D10_TEXTURE3D_DESC desc2; //paramètre nécessaire à l'utilisation de CreateShaderResourceView
    distMap->GetDesc(&desc2);
    D3D10_SHADER_RESOURCE_VIEW_DESC viewDesc;
    ZeroMemory( &viewDesc, sizeof(viewDesc) );
    viewDesc.Format = desc2.Format;
    viewDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE3D;
    viewDesc.Texture3D.MipLevels = desc2.MipLevels;
    hr = g_pd3dDevice->CreateShaderResourceView( distMap, &viewDesc, &g_pTextureRV); //Et cette fonction ne donne pas de résultat
     
    if( FAILED( hr ) )
    	MessageBox(NULL, "Echec de l'allocation de la texture 3D au shader", "Error", MB_OK); //Ce message s'affiche systématiquement au lancement du programme

    Quelqu’un aurait il une idée de ce que je pourrais faire pour obtenir une texture (ID3D10Texture3D) ou ressource (ID3D10Resource) à passer au shader ?

    J’espère avoir été clair, d’avance merci.

  2. #2
    Membre chevronné

    Inscrit en
    Août 2007
    Messages
    300
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 300
    Par défaut
    Je n'ai pas bien lu votre code, mais typiquement pour faire ce que vous souhaitez faire il faut faire une texture avec un usage D3D10_USAGE_DYNAMIC, un access flags D3D10_CPU_ACCESS_WRITE et un binding D3D10_BIND_SHADER_RESOURCE, et vous créez la "vue ressource" correspondante, que vous (pub)liez pour vos shaders. De cette manière, vous pouvez modifier depuis le CPU une texture accessible par le GPU dans ses shaders.
    Cependant, je ne recommande pas cette approche pratique mais aveugle, parce qu'elle taxe inconsidérément le driver, qui ne peut pas deviner votre manière d'apporter des modifications à la texture, et risque donc d'être trop conservateur coté performances. Selon votre application, je vous conseille plutôt de considérer une première texture avec usage D3D10_USAGE_STAGING, access flags D3D10_CPU_ACCESS_WRITE, et binding 0. Puis une deuxième texture plus classique avec usage D3D10_USAGE_DEFAULT, access flags 0, et binding D3D10_BIND_SHADER_RESOURCE. (il faut créer la vue ressource d'après cette deuxième texture). Après avoir mis à jour par le CPU la première texture, vous pouvez propager la mise à jour vers vos shaders par un ID3D10Device::CopyResource depuis la première texture vers la deuxième. CopyResource étant asynchrone, il y a moyen de le placer à des endroits quasiment gratuits (VBL, calculs CPU, etc.).

    Remarque sur les commentaires de votre code:
    1) Staging en soi ne donne pas de "droits en écriture ou en lecture" sur la ressource. Cela donne les droits de lecture par le CPU de données situées dans le GPU, ce qui me semble assez éloigné de votre commentaire. Pensiez-vous aux CpuAccessFlags?
    2) il est tout à fait autorisé (et même très fortement recommandé!) de ne pas mettre de D3D10_CPU_ACCESS_WRITE s'il n'est pas nécessaire. Une texture avec D3D10_CPU_ACCESS_READ autorise le driver à certaines optimisations. Bien sur, on ne peut pas les modifier par le CPU.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 3
    Par défaut
    Merci d'avoir prit le temps de statuer sur mon problème. La seconde technique que vous évoquez correspond à ce que je souhaite obtenir et je serais bien sot de na pas suivre des conseils avisés lorsque l'on m'en donne.

    Pour ce qui est de mes commentaires, je plaide coupable. Je ne pensais pas aux CpuAccessFlags, je n'avais simplement pas saisit le sens de Staging.
    Quand aux CpuAccessFlags READ & WRITE, je ne suis parvenu qu'à taton à faire en sorte que la fonction D3DX10CreateTextureFromFile se termine autrement que par un échec. Mon idée selon laquelle associer ces deux flags est nécessaire est certainement fausse.

    J'essaierais de mettre tout cela en application dès demain. Soyez remercié pour ces critiques qui, je n'en doute pas, m'aideront à résoudre mon problème.

Discussions similaires

  1. Réponses: 2
    Dernier message: 15/12/2014, 09h48
  2. Réponses: 3
    Dernier message: 14/12/2010, 19h35
  3. Réponses: 0
    Dernier message: 24/02/2009, 04h36
  4. [FBO+GLSL]rendu dans plus d'une texture à la fois
    Par Kurisu dans le forum OpenGL
    Réponses: 4
    Dernier message: 20/06/2008, 18h53
  5. Copier une texture dans une autre?
    Par supergrey dans le forum DirectX
    Réponses: 9
    Dernier message: 28/07/2004, 11h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo