Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

21

10.07.2010, 18:28

Hm das ist sehr komisch. Stimmen deine Texturkoordinaten sicher? Wie füllst du die Textur jetzt?

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

22

11.07.2010, 12:14

Die Texture Koordinaten stimmen definitiv und ich fülle die Bild Daten mit:

C-/C++-Quelltext

1
DeviceContext->UpdateSubresource(Texture2D, 0, 0, ImageBuffer, 0, 0);

Dabei zeigt ImageBuffer auf einen unsigned char Puffer mit der Größe Width*Height*4, genau so, wie ich es mit dem Format angegeben habe. (DXGI_FORMAT_R8G8B8A8_UNORM)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

23

11.07.2010, 12:22

Dein RowPitch ist 0, was du siehst ist also vollkommen korrekt ;)

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

24

11.07.2010, 17:52

Stimmt, jetzt funktioniert's, danke! :)

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

25

12.07.2010, 11:56

Jetzt hab ich noch mal ne Frage zu den Constant Buffers in HLSL.

Den Constant Buffer erstelle ich so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
D3D11_BUFFER_DESC BufferDesc;
ZeroMemory(&BufferDesc, sizeof(D3D11_BUFFER_DESC));

BufferDesc.Usage            = D3D11_USAGE_DEFAULT;
BufferDesc.ByteWidth        = 1024; // hier weiß ich noch nicht wie ich ermitteln kann, wie viel Bytes ich für einen individuellen Shader brauche
BufferDesc.BindFlags        = D3D11_BIND_CONSTANT_BUFFER;
BufferDesc.CPUAccessFlags   = 0;

Device_->CreateBuffer(&BufferDesc, 0, &ConstantBuffer);


Mein Constant Buffer im Shader sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct SLight
{
    int Model; // Problem ist hier ...
    float4 Position;
    float4 Diffuse, Ambient, Specular;
};

cbuffer ConstantBuffer
{
    float4x4 WorldMatrix, ViewMatrix, ProjectionMatrix;
    
    float4 DiffuseColor;
    
    int LightCount; // ... und hier
    SLight Lights[8];
}

Das Problem liegt bei "LightCount" und "Model". Jetzt denkt ihr wahrscheinlich das Problem sei der Typ "int" aber ich habe es auch schon mit float ausprobiert.
Ich vermute, dass die Datentypen immer float4 oder float4x4 sein müssen. Aber warum kann ich nicht eifach nur "float" oder nur "int" verwenden?
Das sollte doch auch möglich sein.

Ich übergebe die Daten so:

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
struct SConstants
{
    struct SLight
    {
    int Model;
        float Position[4];
        float Diffuse[4], Ambient[4], Specular[4];
    };
    
    float WorldMatrix[16], ViewMatrix[16], ProjectionMatrix[16];
    
    float DiffuseColor[4];
    
    int LightCount;
    SLight Lights[8];
};

SConstants TempBuffer;

/* ... Daten fuellen ... */

DeviceContext_->UpdateSubresource(ConstantBuffer, 0, 0, &TempBuffer, 0, 0);


Muss ich hier wieder auf die anderen Parameter von "UpdateSubresource" achten? Oder was mache ich sonst falsch?

bepo

Frischling

Beiträge: 33

Wohnort: Bayern

Beruf: Schüler

  • Private Nachricht senden

26

13.07.2010, 20:50

Zitat

// hier weiß ich noch nicht wie ich ermitteln kann, wie viel Bytes ich für einen individuellen Shader brauche
D3D11_SHADER_BUFFER_DESC ::Size via ID3D11ShaderReflectionConstantBuffer::GetDesc



Packing Rules for Constant Variables

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
cbuffer ConstantBuffer
{
    float4x4  WorldMatrix; // Offset: 0, size: 64
    float4x4 ViewMatrix; // Offset:  64, size: 64
    float4x4 ProjectionMatrix; // Offset: 128, size: 64
    float4  DiffuseColor; // Offset: 192, size: 16
    int LightCount; // Offset: 208, size: 4
    SLight Lights[8]; //  Offset: 224, size: 640
}


So sollte das funktionieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct SLight
{
    int Model; int pad[3];
    float4 Position;
    float4 Diffuse, Ambient, Specular;
};

cbuffer ConstantBuffer
{
    float4x4 WorldMatrix, ViewMatrix, ProjectionMatrix;
    
    float4 DiffuseColor;
    
    int LightCount; int pad[3];
    SLight Lights[8];
}

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

27

13.07.2010, 20:56

Aber warum muss man dieses "pad[3]" einbauen? Warum muss man immer für 16 Byte bzw. 4 Integer oder Floats sorgen?? ?(
Das ist doch Mist.

bepo

Frischling

Beiträge: 33

Wohnort: Bayern

Beruf: Schüler

  • Private Nachricht senden

28

14.07.2010, 11:20

Hoffentlich ist das jetzt nicht zu großer Mist:
Durch die SIMD-Architektur (add , mad , dp4 , usw.) werden Instruktionen immer auf 4 Fließkommazahlen gleichzeitig angewendet. D.h. es sollten diese auch immer auf einmal aus dem Speicher geholt werden. Daraus ergibt sich die Ausrichtung des Speichers an Vielfachen der Größe eines aus 4 Fielßkommazahlen bestehenden Registers. Pro Takt kann im Idealfall (warmer Cache) eines ausgelesen werden. Würden Daten (z.B. ein Vektor) jetzt über mehrere Register verteilt, wären mehrere Take zum Auslesen und Zusammensetzen über die Registergrenze hinweg nötig. Da das wiederum in einer auf unbedingte Leistung ausgelegten Architektur eher suboptimal wäre, wird versucht das zu vermeiden.
C++ Compiler (und vermutlich auch die aller anderen Sprachen) machen das auch, da die x86-Architektur auf 4 Bytes ausgerichtet ist. Allerdings transparent und per Option ausschaltbar (z.B. #pragma pack(1) struct { char a; int b; } wird zu "abbbb" (pro Buchstabe ein Byte des entsprechenden Feldes), mit pack(4) zu "a...bbbb"). Solange man alles einheitlich kompiliert stellt das kein Problem dar, aber hinsichtlich der Performance (aber auf Kosten des Speichers) ist es wie schon gesagt weniger optimal. Beim schreiben von Strukturen im Binärformat in Dateien ist es hingegen eine ziemlich gemeine Stolperfalle, wenn z.B. der eine die gesamte Struktur auf 4 Bytes ausgerichtet auf einmal schreibt (fwrite(handle, sizeof(MyStruct, 1), src), der andere anschließend jedes Feld einzeln per fread(handle, sizeof(myField), 1, dst) ausliest oder mit einer anderen Ausrichtung die gesamte Struktur ausliest, usw.
Das gleiche Problem besteht genauso beim Übergang zwischen C++ und der Grafikarchitektur. Der C++-Compiler kennt die Ausrichtung der Zielarchitektur nicht, weshalb das von Hand zu machen ("pad[3]") oder auf Hilfsmittel wie D3DReflect zurückzugreifen ist, um mehr über die Struktur des Buffers zu erfahren (der Quelltext des Effects11-Frameworks liegt dem SDK bei, um einmal genau zu sehen, wie man das optimal löst). Das ist Mist, aber notwendig.
Ob und wie man genau diese Ausrichtung dem C++-Compiler irgendwie beibringen könnte, weiß ich nicht.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

29

14.07.2010, 11:37

Ist dieses pad[3] wirklich notwendig, ich bezweifle das nämlich? Ein int hat 4 Byte, der struct wäre also auch ohne manuelles padding auf 4 Byte gepackt. Desweiteren sind moderne GPUs schon lange keine float4 SIMD Architekturen mehr (GeForce 7 war da z.B. die letzte bei NVIDIA, ATI hat das noch etwas länger betrieben afaik).

EDIT: Ok, es scheint wohl tatsächlich notwendig zu sein: http://msdn.microsoft.com/en-us/library/bb509632.aspx

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (14.07.2010, 12:01)


bepo

Frischling

Beiträge: 33

Wohnort: Bayern

Beruf: Schüler

  • Private Nachricht senden

30

14.07.2010, 12:56

Mit den tatsächlichen Architekturen selbst, könnte ich inzwischen falsch liegen. Das nVidia seit der 8000er-Serie eine Skalararchitektur verwendet, weiß ich. Bei ATI/AMD habe ich noch irgendetwas mit 5D-Registern im Kopf, weshalb die auf 160*5=800, 320*5=1600, usw. Streamprocessoren kommen. Das scheint bei denen heute noch so zu sein. (Gibt auch des öfteren Streit in Foren unter Fanboys, ob nVidia jetzt mit 240 Streamprozessoren (GTX280) an die 800 (4870er) von AMD rankommt.)

Zitat

Ich verstehe das so, dass zumindest die Spezifikation von HLSL noch immer einen SIMD-Ansatz verfolgt. Variablen innerhalb eines Registers können einfach per Squizzle-Operator in die richtige Ordnung gebracht werden, registerübergreifend jedoch nicht.
Außerdem kommt es hier eigentlich nicht darauf an, wie die Architektur aufgebaut ist, sondern was spezifiziert ist, oder? Der Grafik-Treiber kann mit dem HLSL-Bytecode damit anstellen, was er will, solange dabei das erwartete Ergebnis rauskommt. Direct3D11 unterstützt noch Direct3D9-Level Hardware, was Kompatibilität von HLSL zu SIMD-Hardware wie GeForce7 und abwärts erfordert (als compile-target z.B.: ps_4_0_level_9_3).

[EDIT] Habe nach dem Essen das edit noch nicht gesehen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »bepo« (14.07.2010, 13:59)


Werbeanzeige