Jump to content
  • Advertisement
Sign in to follow this  
DaveHunter

HLSL Issues

This topic is 2485 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've noticed that D3D9 tends to have issues in Windows 7, so I want to create an interface in my next game that chooses between D3D9 and D3D11 based on the end-user's OS.

The issue I'm having is with code found in a D3D11 Tutorial. The HLSL data seems to be loading properly when the call is made to D3DX11CompileFromFile, but when the calls are made to CreatePixelShader and CreateVertexShader, it's failing out with E_INVALIDARG. The full code from the tutorial (including the HLSL) file is listed below (I've removed my debugging code). The trouble macro is at the end of the program. Does anyone know where I'm hitting the issue?

// include the basic windows header files and the Direct3D header files
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>

// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

// global declarations
IDXGISwapChain *swapchain; // the pointer to the swap chain interface
ID3D11Device *dev; // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context
ID3D11RenderTargetView *backbuffer; // the pointer to our back buffer
ID3D11InputLayout *pLayout; // the pointer to the input layout
ID3D11VertexShader *pVS; // the pointer to the vertex shader
ID3D11PixelShader *pPS; // the pointer to the pixel shader
ID3D11Buffer *pVBuffer; // the pointer to the vertex buffer

// a struct to define a single vertex
struct VERTEX{FLOAT X, Y, Z; D3DXCOLOR Color;};
// function prototypes
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void RenderFrame(void); // renders a single frame
void CleanD3D(void); // closes Direct3D and releases memory
void InitGraphics(void); // creates the shape to render
void InitPipeline(HWND); // loads and prepares the shaders

// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;

ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
// wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass";

RegisterClassEx(&wc);

RECT wr = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

hWnd = CreateWindowEx(NULL,
L"WindowClass",
L"Our First Direct3D Program",
WS_OVERLAPPEDWINDOW,
300,
30,
wr.right - wr.left,
wr.bottom - wr.top,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hWnd, nCmdShow);

// set up and initialize Direct3D
InitD3D(hWnd);

// enter the main loop:

MSG msg;

while(TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if(msg.message == WM_QUIT)
break;
}

RenderFrame();
}

// clean up DirectX and COM
CleanD3D();

return msg.wParam;
}


// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}

return DefWindowProc (hWnd, message, wParam, lParam);
}


// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;

// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferDesc.Width = SCREEN_WIDTH;
scd.BufferDesc.Height = SCREEN_HEIGHT;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 1; // how many multisamples
scd.SampleDesc.Quality = 0; // multisample quality level
scd.Windowed = TRUE; // windowed/full-screen mode
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);


// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();

// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, NULL);


// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCREEN_WIDTH;
viewport.Height = SCREEN_HEIGHT;

devcon->RSSetViewports(1, &viewport);

InitPipeline(hWnd);
InitGraphics();
}


// this is the function used to render a single frame
void RenderFrame(void)
{
// clear the back buffer to a deep blue
devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

// do 3D rendering on the back buffer here
UINT stride = (unsigned int)sizeof(VERTEX);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);

devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// devcon->Draw(3,0);

// switch the back buffer and the front buffer
swapchain->Present(0, 0);
}


// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
swapchain->SetFullscreenState(false, NULL);

// close and release all existing COM objects
pLayout->Release();
// pVS->Release();
// pPS->Release();
pVBuffer->Release();
swapchain->Release();
backbuffer->Release();
dev->Release();
devcon->Release();
}

// this is the function that creates the shape to render
void InitGraphics()
{
// create a triangle using the VERTEX struct
VERTEX OurVertices[] =
{
{0.0f, 0.5f, 0.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},
{0.45f, -0.5, 0.0f, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},
{-0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)}
};


// create the vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));

bd.Usage = D3D11_USAGE_DYNAMIC; // write access access by CPU and GPU
bd.ByteWidth = sizeof(VERTEX) * 3; // size is the VERTEX struct * 3
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // use as a vertex buffer
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // allow CPU to write in buffer

dev->CreateBuffer(&bd, NULL, &pVBuffer); // create the buffer


// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurVertices, sizeof(OurVertices)); // copy the data
devcon->Unmap(pVBuffer, NULL); // unmap the buffer
}

// this function loads and prepares the shaders
void InitPipeline(HWND hWnd)
{
// load and compile the two shaders
HRESULT result;

ID3D10Blob *VS, *PS;
D3DX11CompileFromFile(L"../DX11/shaders.hlsl", NULL, NULL, "VShader", "vs_2_0", 0, 0, 0, &VS, 0, NULL);
D3DX11CompileFromFile(L"../DX11/shaders.hlsl", NULL, NULL, "PShader", "ps_2_0", 0, 0, 0, &PS, 0, NULL);

// encapsulate both shaders into shader objects
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);

// set the shader objects
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);

// create the input layout object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};

dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
devcon->IASetInputLayout(pLayout);
}


Here's the code for the HLSL file.

struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
VOut output;

output.position = position;
output.color = color;

return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}

Share this post


Link to post
Share on other sites
Advertisement
I found the issue. The code is sound. If anyone else is using the same tutorials and encounters this issue, I resolved the issue by changing the shader version from 5_0 to 4_0. Apparently my year-old laptop doesn't have shader 5 support (imagine that).

Share this post


Link to post
Share on other sites

I found the issue. The code is sound. If anyone else is using the same tutorials and encounters this issue, I resolved the issue by changing the shader version from 5_0 to 4_0. Apparently my year-old laptop doesn't have shader 5 support (imagine that).


Laptop GPU's often cut corners... this is no surprise.

Share this post


Link to post
Share on other sites

I found the issue. The code is sound. If anyone else is using the same tutorials and encounters this issue, I resolved the issue by changing the shader version from 5_0 to 4_0. Apparently my year-old laptop doesn't have shader 5 support (imagine that).



You are aware that the sample code is trying to compile as ps_2_0 and vs_2_0 with SM 4.0 semantics? You might want to check return codes from D3D functions before assuming they are correct, this is actually a best practise when writing D3D code. Also if you pass in ID3D10Blob **ppErrorMsgs to CompileFromFile you can output the compile error you are getting, the error blob should be just a text string when you get it back.

Share this post


Link to post
Share on other sites
I'm personally puzzled about the "issues" that you mention D3D9 has in Windows 7; I'm not seeing any difficulties in my own code...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!