[C++] ID3D10Blob* ist immer NULL

06/25/2014 22:31 lolxdflyx3#1
Hi,
ich hab angefangen mit DirectX ein kleines Spiel zu schreiben.
Um das Laden der Shader zu vereinfachen wollte ich mir eine Funktion schreiben:
So sieht sie aus...
Der 1. Teil funktioniert.
Das Problem ist, dass der 2. Teil nie ausgeführt wird, weil pBuffer immer NULL ist. :/

Aufrufen tu ich sie so:
Code:
	//Compile Shaders from shader file
	CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, VS_Buffer, VS, NULL);
Ich bin mir relativ sicher, dass es an dem Übergabeparameter pBuffer liegt. Nur weiß ich nicht warum dieser immer NULL ist :/

Hat jemand ne Ahnung wieso das so ist? Ich kenn mich mit Shader in DirectX noch nicht sooo aus!

mfg
lolxdfly
06/26/2014 23:40 Mostey#2
Und wo ist die Deklaration (+ Definition) von pBuffer? Vielleicht reservierst du einfach keinen Speicher dafür, bei dem bloßen Funktionsaufruf kann ich nichts relevantes sehen weil dort kaum mit diesem pBuffer gearbeitet wird.

Übrigens hat das nicht mehr viel mit C++ zutun, das ist C.
06/27/2014 13:44 lolxdflyx3#3
Quote:
Originally Posted by Mostey View Post
Und wo ist die Deklaration (+ Definition) von pBuffer? Vielleicht reservierst du einfach keinen Speicher dafür, bei dem bloßen Funktionsaufruf kann ich nichts relevantes sehen weil dort kaum mit diesem pBuffer gearbeitet wird.
pBuffer ist in den Funktionsparamentern deklariert:
Code:
bool CreateShader(char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3D10Blob** ppBuffer, ID3D10Blob* pBuffer, ID3D11VertexShader* VS, ID3D11PixelShader* PS)
Definiert wird es durch die Übergabe von VS_Buffer:
Code:
CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, VS_Buffer, VS, NULL);
Quote:
Originally Posted by Mostey View Post
Übrigens hat das nicht mehr viel mit C++ zutun, das ist C.
Mag sein... C und C++ teilen sich ja eh eine Sektion hier :)
06/27/2014 22:30 Nightblizard#4
Code:
void foo(int bar)
{
   //...
}
"bar" hat den falschen Werten, weshalb "foo" fehlschlägt. Was ist an "foo" falsch?
06/28/2014 03:15 Mostey#5
Quote:
Originally Posted by lolxdflyx3 View Post
pBuffer ist in den Funktionsparamentern deklariert:
Code:
bool CreateShader(char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3D10Blob** ppBuffer, ID3D10Blob* pBuffer, ID3D11VertexShader* VS, ID3D11PixelShader* PS)
Definiert wird es durch die Übergabe von VS_Buffer:
Code:
CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, VS_Buffer, VS, NULL);

Mag sein... C und C++ teilen sich ja eh eine Sektion hier :)
Ja, die Sprachen teilen sich ne Sektion aber man sollte schon wissen, in welcher Sprache man programmiert. Du hast nämlich im Titel C++ geschrieben, daher gehe ich davon aus, das du es nicht weißt oder bis eben nicht wusstest.

Du brauchst nun logischerweise ne Variable vom Datentyp ID3D10Blob oder eben einen Pointer darauf, letztendlich musst du sowieso immer einen Pointer übergeben. Wo liegt das Problem? Wie Nightblizard schon erwähnt hat, können wir dir nicht helfen, wenn du nicht das postest, was hier relevant ist.
06/28/2014 11:03 lolxdflyx3#6
Ich weiß nicht genau was genau dir noch an Code fehlt.. :/
Hier sind noch ein paar Sachen, die damit zutun haben:
Code:
ID3D10Blob* VS_Buffer;
An der Shader-Datei kann es nicht liegen, da es ohne die nutzung vom 2. Teil der CreateShader funktion einwandfrei funktioniert:
Code:
	CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, VS_Buffer, VS, NULL); // 2. Teil auskommentiert
	//Create the Shader Objects
	hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
	if (FAILED(hr))
	{
		Error("Failed to create Shader: Effects.fx");
		VS_Buffer->Release();
		return false;
	}

        //...

	//Create the Input Layout
	hr = d3d11Device->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(),
		VS_Buffer->GetBufferSize(), &vertLayout); // hier noch etwas, was mit VS_Buffer zutun hat
06/28/2014 15:16 MrSm!th#7
Quote:
Originally Posted by Mostey View Post
Übrigens hat das nicht mehr viel mit C++ zutun, das ist C.
Wäre mir neu, dass C Klassen hat.
Quote:
Originally Posted by lolxdflyx3 View Post
Ich weiß nicht genau was genau dir noch an Code fehlt.. :/
Hier sind noch ein paar Sachen, die damit zutun haben:
Code:
ID3D10Blob* VS_Buffer;
An der Shader-Datei kann es nicht liegen, da es ohne die nutzung vom 2. Teil der CreateShader funktion einwandfrei funktioniert:
Code:
CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, VS_Buffer, VS, NULL); // 2. Teil auskommentiert
//Create the Shader Objects
hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
if (FAILED(hr))
{
Error("Failed to create Shader: Effects.fx");
VS_Buffer->Release();
return false;
}

        //...

//Create the Input Layout
hr = d3d11Device->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(),
VS_Buffer->GetBufferSize(), &vertLayout); // hier noch etwas, was mit VS_Buffer zutun hat
Weist du VS_Buffer denn auch einen Wert zu?
06/28/2014 15:57 lolxdflyx3#8
Quote:
Originally Posted by MrSm!th View Post
Wäre mir neu, dass C Klassen hat.


Weist du VS_Buffer denn auch einen Wert zu?
Ja, ich denke schon...
Müsste hier passieren:
Code:
	hr = D3DX11CompileFromFile(tmp, 0, 0, szEntryPoint, szShaderModel,
		dwShaderFlags, 0, 0, ppBuffer, 0, 0); // ppBuffer = &VS_Buffer
Ich denke nicht, dass es an VS_Buffer liegt. Schließlich läuft folgender Code ja fehlerfrei:
Code:
	hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
	if (FAILED(hr))
	{
		Error("Failed to create Shader: Effects.fx");
		VS_Buffer->Release();
		return false;
	}
Nur wenn ich VS_Buffer übergebe friert es ein, sobald ich pBuffer "anspreche".
06/28/2014 16:15 Jeoni#9
Joa, ist doch klar: pBuffer ist ja ein kopierter von dem ungültigen Pointer vor dem Funktionsaufruf.
Besser du übergibst nur ppBuffer, kreierst das Objekt dann entsprechend und nutzt in CreateShader *ppBuffer, wenn du den einfachen Pointer brauchst. Ferner kreierst du in CreateShader das ShaderObjekt auf das Argument. Und das wird nicht nach außen gereicht. So sollte es klappen (kannst an einigen Stellen auch implizite Referenzen ('&') statt Pointer nehmen, wenn du willst):
Code:
bool CreateShader(char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3D10Blob** ppBuffer, ID3D11VertexShader** VS, ID3D11PixelShader** PS)
{
	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
	// Setting this flag improves the shader debugging experience, but still allows 
	// the shaders to be optimized and to run exactly the way they will run in 
	// the release configuration of this program.
	dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

	sprintf(tmp, "%s%s", pShaders, szFileName);

	hr = D3DX11CompileFromFile(tmp, 0, 0, szEntryPoint, szShaderModel,
		dwShaderFlags, 0, 0, ppBuffer, 0, 0);
	if (FAILED(hr))
	{
		sprintf(tmp, "Failed to compile Shader: %s : %s", szFileName, szEntryPoint);
		Error(tmp);
		return false;
	}


	if (*ppBuffer != NULL)
	{
		if (PS == NULL)
			hr = d3d11Device->CreateVertexShader((*ppBuffer)->GetBufferPointer(), (*ppBuffer)->GetBufferSize(), NULL, VS);
		else
			hr = d3d11Device->CreatePixelShader((*ppBuffer)->GetBufferPointer(), (*ppBuffer)->GetBufferSize(), NULL, PS);
		if (FAILED(hr))
		{
			sprintf(tmp, "Failed to create Shader: %s : %s", szFileName, szEntryPoint);
			Error(tmp);
			(*ppBuffer)->Release();
			return false;
		}
	}

	return true;
}
Aufruf dann halt mit:
Code:
CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, &VS, NULL);
Sowohl VS, wie auch VS_Buffer sollten nun gültig sein und du kannst mit ihnen arbeiten ;)

MfG
Jeoni
06/28/2014 16:41 lolxdflyx3#10
Quote:
Originally Posted by Jeoni View Post
Joa, ist doch klar: pBuffer ist ja ein kopierter von dem ungültigen Pointer vor dem Funktionsaufruf.
Besser du übergibst nur ppBuffer, kreierst das Objekt dann entsprechend und nutzt in CreateShader *ppBuffer, wenn du den einfachen Pointer brauchst. Ferner kreierst du in CreateShader das ShaderObjekt auf das Argument. Und das wird nicht nach außen gereicht. So sollte es klappen (kannst an einigen Stellen auch implizite Referenzen ('&') statt Pointer nehmen, wenn du willst):
Code:
bool CreateShader(char* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3D10Blob** ppBuffer, ID3D11VertexShader** VS, ID3D11PixelShader** PS)
{
	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
	// Setting this flag improves the shader debugging experience, but still allows 
	// the shaders to be optimized and to run exactly the way they will run in 
	// the release configuration of this program.
	dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

	sprintf(tmp, "%s%s", pShaders, szFileName);

	hr = D3DX11CompileFromFile(tmp, 0, 0, szEntryPoint, szShaderModel,
		dwShaderFlags, 0, 0, ppBuffer, 0, 0);
	if (FAILED(hr))
	{
		sprintf(tmp, "Failed to compile Shader: %s : %s", szFileName, szEntryPoint);
		Error(tmp);
		return false;
	}


	if (*ppBuffer != NULL)
	{
		if (PS == NULL)
			hr = d3d11Device->CreateVertexShader((*ppBuffer)->GetBufferPointer(), (*ppBuffer)->GetBufferSize(), NULL, VS);
		else
			hr = d3d11Device->CreatePixelShader((*ppBuffer)->GetBufferPointer(), (*ppBuffer)->GetBufferSize(), NULL, PS);
		if (FAILED(hr))
		{
			sprintf(tmp, "Failed to create Shader: %s : %s", szFileName, szEntryPoint);
			Error(tmp);
			(*ppBuffer)->Release();
			return false;
		}
	}

	return true;
}
Aufruf dann halt mit:
Code:
CreateShader("Effects.fx", "VS", "vs_4_0", &VS_Buffer, &VS, NULL);
Sowohl VS, wie auch VS_Buffer sollten nun gültig sein und du kannst mit ihnen arbeiten ;)

MfG
Jeoni
Damit gehts. Genau das, was ich gesucht habe :D
Danke
06/28/2014 17:48 Mostey#11
Quote:
Originally Posted by MrSm!th View Post
Wäre mir neu, dass C Klassen hat.
Mir auch, das könnten allerdings trotzdem normale Structs sein oder gibt es hier ein entscheidendes Merkmal, was ich übersehen habe?
06/28/2014 19:50 snow#12
Quote:
Originally Posted by Mostey View Post
Mir auch, das könnten allerdings trotzdem normale Structs sein oder gibt es hier ein entscheidendes Merkmal, was ich übersehen habe?
Welcher C-Standard erlaubt Structs, (virtuelle) Funktionen zu callen? Nur weil im Code 1x sprintf verwendet wurde, ist das nicht C.
06/29/2014 20:21 MrSm!th#13
Die DirectX Interfaces sind aber keine Structs, simple as that :p