Daten von der Grafikkarte zurück an den Hauptprozessor senden



  • Hallo zusammen
    Ich möchte einige Sachen auf der GPU berechen lassen, welche anschliessend von der CPU weiterverarbeitet werden müssen.

    Hat jemand von each eine Idee, wie man so etwas bewerkstelligen könnte?

    Lg Ishildur



  • Z.B. mit DirectX oder CUDA



  • Das hört sich interessant an! Wie mache ich es mit DirectX?



  • Nun ja, da du keine konkreten Hinweise gibst WAS genau du machen willst, kann ich nur einen möglichen Weg kurz skizzieren:

    Du schreibst dir einen (oder mehrere) Shader, die beschreiben was die GPU machen soll. Dann definierst du 2 Ressourcen: Eine, in die die GPU ihr Ergebnis schreibt und eine andere, in der du das Ergebnis schreibst und auf das dann die CPU zugriff hat (Grund: Es gibt in DX10 keine Ressource, die gleichzeitig von der GPU beschreibbar und von der CPU lesbar ist).
    Der Ablauf ist grob also folgender:

    1. Shader definieren
    2. DEFAULT Ressource (Buffer oder Texture) anlegen und bei der Initialisierung mit Eingabedaten füllen
    3. Shader Code ausführen
    4. Ergebnis aus DEFAULT Ressource kopieren in eine STAGING Ressource (die sind per CPU lesbar), z.B. per ID3D10Device::CopyResource()
    5. STAGING Ressource mappen per Map(). Map liefert dir einen Zeiger auf die Daten. Jetzt hast du die Daten und kannst darauf rumpfuschen wie du willst;)


  • @this->that
    Erst einmal, danke vielmals für dein Engagement! 🙂 Leider muss das Teil eben auch mit Direct3D9 laufen und da habe ich soviel ich weiss, keine solchen Resourcen. Gibt es da trotzdem einen direkteren Weg, als einfach das Rendertarget zu ändern?

    Mfg Ishildur



  • Ishildur schrieb:

    Leider muss das Teil eben auch mit Direct3D9 laufen und da habe ich soviel ich weiss, keine solchen Resourcen.

    Doch, die gibt es da genauso. Auch wenn sich das Ressourcen System von DX10 im Vergleich zu DX9 doch stark verändert hat, gibt es im Großen und ganzen die selben Ressourcen; meistens heißt alles nur ein bißchen anders. In DX9 kannst du genauso in ein Rendertarget rendern und dann das RT mappen (in DX9 heißt die Methode Lock()) und auf die Daten zugreifen.

    Ishildur schrieb:

    Gibt es da trotzdem einen direkteren Weg, als einfach das Rendertarget zu ändern?

    Direkter als einfach in das RT schreiben? Direkter geht es ja eigentlich garnicht und irgendwo muss ja das Ergebnis der GPU Berechnungen hingeschrieben werden.



  • Ok, ich habe das mal versucht, habe aber nun folgendes Problem:

    float arrFlt[8] = {1.0f,1.0f,1.0f,1.0f,0.0f,0.0f,0.0f,0.0f};
    SetVertexShaderConstantF(0,arrFlt,2);

    vs.1.1
    mov oD0,c0
    mov oPos,c1

    Sollte ich nun nicht in in den ersten 4 Bytes im Rendertarget 1.0f drinnstehen? Steht bei mir aber imm 0.0f drinn.

    Gibt es eigentlich eine Möglichkeit, im Shader Literale zu verwenden wie bspw.
    mov oPnt,1.0

    oder soetwas ähnliches?

    Lg Ishildur



  • Alle Eckpunkte Deines Polygons sind identisch und darum wird es vom Rasterizer verworfen und (0,0,0) waere in der Mitte.



  • Nun ja, ich übergebe natürlich eine Punktliste, damit sollte der Rasterizer dass doch zeichnen, oder?

    float arrTmp[] = {0.0f,0.0f,0.0f,0.0f};
    pDv->DrawPrimitiveUP(D3DPT_POINTLIST,1,arrTmp,sizeof(float));



  • Also ich komme echt nicht weiter, hier ist das fragliche Codefragment:

    // determine the content of the code edit - control
      char buf[4096] = {"vs.1.1\nmov oD0,c0\nmov oPos,c1\nmov oPts,c3.x"};
      //GetWindowText(hTbxCod,buf,4096);
    
      // try to assemble the vertex - shader machine instructions
      if(D3DXAssembleShader(buf,strlen(buf),0x00,0x00,0,&pBufShd,&pBufErr) == D3D_OK){
       // create the vertex - shader
       pDv->CreateVertexShader((DWORD*)pBufShd->GetBufferPointer(),&pVs);
       pDv->SetVertexShader(pVs);
       pDv->SetPixelShader(0x00);
    
       float arrTmp1[12] = {1.0f,1.0f,1.0f,1.0f,0.0f,0.0f,0.0f,0.0f,10.0f,10.0f,10.0f,10.0f}; 
       pDv->SetVertexShaderConstantF(0,arrTmp1,3);
    
       pDv->Clear(0,0x00,D3DCLEAR_TARGET,0x000000ff,1.0f,0);
       pDv->BeginScene();
       float arrTmp2[] = {0.0f,0.0f,0.0f,0.0f};
       pDv->DrawPrimitiveUP(D3DPT_POINTLIST,1,arrTmp2,sizeof(float));
       pDv->EndScene();
       pDv->Present(0x00,0x00,0,0x00);
    

    Was mache ich falsch?



  • setfvf vergessen?



  • Braucht man die nicht nur im Zusammenhang mit der Fixed Function Pipeline? 😕



  • Nein, auch die Programmable Pipeline muss das Format deiner Vertices kennen. Aber eigentlich benutzt man da eher eine VertexDeclaration ( http://msdn.microsoft.com/en-us/library/bb174464(VS.85).aspx ) als das alte FVF. Wieso benutzt du eigentlich nicht HLSL?



  • @this->that

    Aha, ok, aber aus welchem Grund muss denn die Programmable Pipeline mein Vertexformat kennen? Das kann ich gerade nicht nachvollziehen. Könntest du mir das erklären?

    Mfg



  • aus welchem Grund muss denn die Programmable Pipeline mein Vertexformat kennen?

    Weil die einzelnen Komponenten Deiner Vertexstruktur irgendwie in die Register des Vertexshaders gelangen muessen.



  • Ja aber tun sie dass nicht sowieso? Die ersten 4 Bytes in V0, die nächsten 4 in V1 usw...



  • Wenn die Vertexdaten einfach stupide der Reihe nach in den 4 Komponenten der VS-Register landen wuerden, muesstest Du die ja erst alle auseinanderpfriemeln.
    Stell Dir vor:

    struct Vertex
    {
      float x,y,z;    // position
      float nx,ny,nz; // normale
      float u,v;      // texturkoordinate
    };
    

    Dann moechte man ja zb:
    v0= x,y,z,1
    v1= nx,by,nz,0
    v2= u,v,0,0

    Nach Deiner Logik waere dann nx in v0.w und ny,nz in v1.xy; das waer' ja wohl nix.



  • Ja, das verstehe ich, aber wieso steht dann in der Doku, isch zitiere:

    A vertex declaration is an IDirect3DVertexDeclaration9 object that defines the data members of a vertex (i.e. texture coordinates, colors, normals, etc.). This data can be useful for implementing vertex shaders and pixel shaders.

    CAN be useful, also wenn ich das richtig verstehe, ist es nicht zwinged erforderlich.

    Naja, wie dem auch sei, ich habe es mal Versuchsweise gemacht, leider ohne Erfolg, es wird noch immer nicht gerendert, hier der angepasste Code:

    // determine the content of the code edit - control
      char buf[4096] = {"vs.1.1\nmov oD0,c0\nmov oPos,c1\nmov oPts,c2.x"};
      //GetWindowText(hTbxCod,buf,4096);   
    
      // try to assemble the vertex - shader machine instructions
      if(D3DXAssembleShader(buf,strlen(buf),0x00,0x00,0,&pBufShd,&pBufErr) == D3D_OK){
       // create the vertex - shader
       pDv->CreateVertexShader((DWORD*)pBufShd->GetBufferPointer(),&pVs);
       pDv->SetVertexShader(pVs);
       pDv->SetFVF(D3DFVF_XYZRHW);
       pDv->SetPixelShader(0x00);
    
       float arrTmp1[12] = {1.0f,0.3f,0.3f,1.0f,0.0f,0.0f,0.0f,0.0f,4.0f,4.0f,4.0f,0.0f}; 
       pDv->SetVertexShaderConstantF(0,arrTmp1,3);
    
       pDv->Clear(0,0x00,D3DCLEAR_TARGET,0xff0000ff,1.0f,0);
       pDv->BeginScene();
       float arrTmp2[] = {0.0f,0.0f,0.0f,0.0f};
       pDv->DrawPrimitiveUP(D3DPT_POINTLIST,1,arrTmp2,4*sizeof(float));
       pDv->EndScene();
       pDv->Present(0x00,0x00,0,0x00);
    


  • Du setzt in deinem Code wieder keine VertexDeclaration, sondern nur das alte FVF.
    Wie ich bereits gesagt habe: Wieso benutzt du frickelige Asm Shader und nicht HLSL Shader?
    Außerdem bestehen deine "Punkte" aus 4mal 0. Wieso erwartest du, dass er da überhaupt was zeichnet? Zeichnet er wenigstens einen roten Hintergrund? (und wieso benutzt du überhaupt überall Hex-Zahlen. Macht den Code IMO nur unnötig kryptisch)



  • @this->that

    Außerdem bestehen deine "Punkte" aus 4mal 0

    Aber ich rendere doch eine POINTLIST??

    pDv->DrawPrimitiveUP(D3DPT_POINTLIST,1,arrTmp2,4*sizeof(float));
    

    Wenn du den "frickeligen Assemblercode" anschaust, wirst du auch bemerken, dass der shader die Vertexdaten überhaupt nicht verarbeitet, sondern nur auch Konstanten zurückgreift... 😉

    Was soll ich denn bei der D3DVERTEXELEMENT::Stream für eine Nummer übergeben, wenn ich DrawPrimitiveUP übergebe?

    Lg


Anmelden zum Antworten