From 6f56942d4405402a2442d398a907298e2b02506c Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Sat, 14 Apr 2012 20:33:56 +0200 Subject: [PATCH] (HLSL) Add skeleton gfx/shader_hlsl.c (for initial use with 360) --- 360/fonts.cpp | 8 +- 360/xdk360_video.cpp | 84 +++--------------- 360/xdk360_video.h | 4 +- gfx/shader_cg.c | 2 +- gfx/shader_hlsl.c | 203 +++++++++++++++++++++++++++++++++++++++++++ gfx/shader_hlsl.h | 34 ++++++++ 6 files changed, 255 insertions(+), 80 deletions(-) create mode 100644 gfx/shader_hlsl.c create mode 100644 gfx/shader_hlsl.h diff --git a/360/fonts.cpp b/360/fonts.cpp index f21b12e785..17e2fead84 100644 --- a/360/fonts.cpp +++ b/360/fonts.cpp @@ -282,7 +282,7 @@ static const char g_strFontShader[] = "uniform float4 Color : register(c1);\n" "uniform float2 TexScale : register(c2);\n" "sampler FontTexture : register(s0);\n" - "VS_OUT FontVertexShader( VS_IN In )\n" + "VS_OUT main_vertex( VS_IN In )\n" "{\n" "VS_OUT Out;\n" "Out.Position.x = (In.Pos.x-0.5);\n" @@ -295,7 +295,7 @@ static const char g_strFontShader[] = "Out.ChannelSelector = In.ChannelSelector;\n" "return Out;\n" "}\n" - "float4 FontPixelShader( VS_OUT In ) : COLOR0\n" + "float4 main_fragment( VS_OUT In ) : COLOR0\n" "{\n" "float4 FontTexel = tex2D( FontTexture, In.TexCoord0 );\n" "if( dot( In.ChannelSelector, float4(1,1,1,1) ) )\n" @@ -364,7 +364,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font) ID3DXBuffer* pShaderCode; hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 , - NULL, NULL, "FontVertexShader", "vs.2.0", 0,&pShaderCode, NULL, NULL ); + NULL, NULL, "main_vertex", "vs.2.0", 0,&pShaderCode, NULL, NULL ); if (SUCCEEDED(hr)) { hr = pd3dDevice->CreateVertexShader( ( unsigned long * )pShaderCode->GetBufferPointer(), @@ -376,7 +376,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font) { // Step #3, create my pixel shader hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 , - NULL, NULL, "FontPixelShader", "ps.2.0", 0,&pShaderCode, NULL, NULL ); + NULL, NULL, "main_fragment", "ps.2.0", 0,&pShaderCode, NULL, NULL ); if ( SUCCEEDED(hr)) { hr = pd3dDevice->CreatePixelShader( ( DWORD* )pShaderCode->GetBufferPointer(), diff --git a/360/xdk360_video.cpp b/360/xdk360_video.cpp index 0a46ee15cb..a77bc2dad1 100644 --- a/360/xdk360_video.cpp +++ b/360/xdk360_video.cpp @@ -19,6 +19,7 @@ #include "../driver.h" #include "xdk360_video.h" #include "xdk360_video_resources.h" +#include "../gfx/hlsl_shader.h" #include "../console/console_ext.h" #include "../general.h" #include "../message.h" @@ -33,17 +34,6 @@ static bool g_first_msg; unsigned g_frame_count; void *g_d3d; -struct hlsl_program_t -{ - D3DXHANDLE vid_size_f; - D3DXHANDLE tex_size_f; - D3DXHANDLE out_size_f; - D3DXHANDLE vid_size_v; - D3DXHANDLE tex_size_v; - D3DXHANDLE out_size_v; - XMMATRIX modelViewProj; -} hlsl_program; - struct XPR_HEADER { unsigned long dwMagic; @@ -199,11 +189,11 @@ static void xdk360_gfx_free(void * data) if (!vid) return; + hlsl_deinit(); + D3DResource_Release((D3DResource *)vid->lpTexture); D3DResource_Release((D3DResource *)vid->vertex_buf); - D3DResource_Release((D3DResource *)vid->pVertexDecl); - D3DResource_Release((D3DResource *)vid->pPixelShader); - D3DResource_Release((D3DResource *)vid->pVertexShader); + D3DResource_Release((D3DResource *)vid->v_decl); D3DDevice_Release(vid->xdk360_render_device); Direct3D_Release(); @@ -298,7 +288,8 @@ static void xdk360_set_orientation(void * data, uint32_t orientation) break; } - hlsl_program.modelViewProj = XMMatrixRotationZ(angle); + hlsl_use(vid->xdk360_render_device, 0); + hlsl_set_proj_matrix(XMMatrixRotationZ(angle)); } static void xdk360_set_aspect_ratio(void * data, uint32_t aspectratio_index) @@ -355,54 +346,7 @@ static void *xdk360_gfx_init(const video_info_t *video, const input_driver_t **i // D3DCREATE_HARDWARE_VERTEXPROCESSING is ignored on 360 ret = Direct3D_CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &vid->d3dpp, &vid->xdk360_render_device); - ID3DXBuffer* pShaderCodeV = NULL; - ID3DXBuffer* pShaderCodeP = NULL; - ID3DXBuffer* pErrorMsg = NULL; - - ret = D3DXCompileShaderFromFile( - g_settings.video.cg_shader_path, //filepath - NULL, //macros - NULL, //includes - "main_vertex", // main function - "vs_2_0", // shader profile - 0, // flags - &pShaderCodeV, // compiled operations - &pErrorMsg, // errors - NULL); // constants - - if (SUCCEEDED(ret)) - { - SSNES_LOG("Vertex shader program from [%s] successfully compiled.\n", "game:\\media\\shaders\\stock.cg"); - ret = D3DXCompileShaderFromFile( - g_settings.video.cg_shader_path, //filepath - NULL, //macros - NULL, //includes - "main_fragment", // main function - "ps_2_0", // shader profile - 0, // flags - &pShaderCodeP, // compiled operations - &pErrorMsg, // errors - NULL); // constants - } - - if (FAILED(ret)) - { - if(pErrorMsg) - SSNES_LOG("%s\n", (char*)pErrorMsg->GetBufferPointer()); - D3DDevice_Release(vid->xdk360_render_device); - Direct3D_Release(); - free(vid); - return NULL; - } - else - { - SSNES_LOG("Pixel shader program from [%s] successfully compiled.\n", "game:\\media\\shaders\\stock.cg"); - } - - vid->pVertexShader = D3DDevice_CreateVertexShader((const DWORD*)pShaderCodeV->GetBufferPointer()); - vid->pPixelShader = D3DDevice_CreatePixelShader((const DWORD*)pShaderCodeP->GetBufferPointer()); - pShaderCodeV->Release(); - pShaderCodeP->Release(); + hlsl_init(NULL); vid->lpTexture = (D3DTexture*) D3DDevice_CreateTexture(512, 512, 1, 1, 0, D3DFMT_LIN_X1R5G5B5, 0, D3DRTYPE_TEXTURE); @@ -435,7 +379,7 @@ static void *xdk360_gfx_init(const video_info_t *video, const input_driver_t **i D3DDECL_END() }; - vid->pVertexDecl = D3DDevice_CreateVertexDeclaration(VertexElements); + vid->v_decl = D3DDevice_CreateVertexDeclaration(VertexElements); D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0, FALSE); @@ -459,10 +403,10 @@ static bool xdk360_gfx_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { xdk360_video_t *vid = (xdk360_video_t*)data; - g_frame_count++; D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0, FALSE); + g_frame_count++; if (vid->last_width != width || vid->last_height != height) { @@ -490,9 +434,8 @@ static bool xdk360_gfx_frame(void *data, const void *frame, vid->last_height = height; } - vid->xdk360_render_device->SetVertexShaderConstantF(0, (FLOAT*)&hlsl_program.modelViewProj, 4); - - //TODO: Update the shader constants + hlsl_use(vid->xdk360_render_device, 0); + hlsl_set_params(vid->xdk360_render_device); D3DLOCKED_RECT d3dlr; D3DTexture_LockRect(vid->lpTexture, 0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK); @@ -510,10 +453,7 @@ static bool xdk360_gfx_frame(void *data, const void *frame, D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); - D3DDevice_SetVertexShader(vid->xdk360_render_device, vid->pVertexShader); - D3DDevice_SetPixelShader(vid->xdk360_render_device, vid->pPixelShader); - - D3DDevice_SetVertexDeclaration(vid->xdk360_render_device, vid->pVertexDecl); + D3DDevice_SetVertexDeclaration(vid->xdk360_render_device, vid->v_decl); D3DDevice_SetStreamSource_Inline(vid->xdk360_render_device, 0, vid->vertex_buf, 0, sizeof(DrawVerticeFormats)); diff --git a/360/xdk360_video.h b/360/xdk360_video.h index aefe24a265..5e31d1bb17 100644 --- a/360/xdk360_video.h +++ b/360/xdk360_video.h @@ -48,11 +48,9 @@ typedef struct xdk360_video unsigned last_height; IDirect3D9* xdk360_device; IDirect3DDevice9* xdk360_render_device; - IDirect3DVertexShader9 *pVertexShader; - IDirect3DPixelShader9* pPixelShader; - IDirect3DVertexDeclaration9* pVertexDecl; IDirect3DVertexBuffer9* vertex_buf; IDirect3DTexture9* lpTexture; + IDirect3DVertexDeclaration9* v_decl; D3DPRESENT_PARAMETERS d3dpp; XVIDEO_MODE video_mode; } xdk360_video_t; diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index d48850c58c..4c6c71c7f4 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -715,7 +715,7 @@ static bool load_imports(const char *dir_path, config_file_t *conf) state_tracker = state_tracker_init(&tracker_info); if (!state_tracker) - SSNES_WARN("Failed to init state tracker.\n"); + SSNES_WARN("Failed to initialize state tracker.\n"); #ifdef HAVE_PYTHON if (script) diff --git a/gfx/shader_hlsl.c b/gfx/shader_hlsl.c new file mode 100644 index 0000000000..a73ad70e29 --- /dev/null +++ b/gfx/shader_hlsl.c @@ -0,0 +1,203 @@ +/* SSNES - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * SSNES is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with SSNES. + * If not, see . + */ + +#include "shader_hlsl.h" +#ifdef _XBOX +#include +#endif + +struct hlsl_program +{ + IDirect3DVertexShader9 *vprg; + IDirect3DPixelShader9 *fprg; + D3DXHANDLE vid_size_f; + D3DXHANDLE tex_size_f; + D3DXHANDLE out_size_f; + D3DXHANDLE vid_size_v; + D3DXHANDLE tex_size_v; + D3DXHANDLE out_size_v; + XMMATRIX mvp; +}; + +static struct hlsl_program prg[SSNES_HLSL_MAX_SHADERS]; +static bool hlsl_active = false; + +static const char *stock_hlsl_program = + "void main_vertex" + "(" + " float2 position : POSITION," + " float2 texCoord : TEXCOORD0," + " uniform float4x4 modelViewProj : register(c0)," + " out float4 oPosition : POSITION," + " out float2 otexCoord : TEXCOORD" + ")" + "{" + " oPosition = mul(modelViewProj, float4(position, 0.0, 1.0));" + " otexCoord = texCoord;" + "}" + "" + "struct output" + "{" + " float4 color: COLOR;" + "}" + "" + "struct input" + "{" + " float2 video_size;" + " float2 texture_size;" + " float2 output_size;" + "}" + "" + "output main_fragment(float2 tex : TEXCOORD0, uniform sampler2D decal : register(s0), uniform input IN)" + "{" + " output OUT;" + " OUT.color = tex2D(decal, tex);" + " return OUT;" + "}"; + +void hlsl_set_proj_matrix(XMMATRIX rotation_value) +{ + if (hlsl_active && prg[active_index].mvp) + prg[active_index].mvp = rotation_value; +} + +void hlsl_set_params(IDirect3DDevice9 * device) +{ + if (!hlsl_active) + return; + + if (prg[active_index].mvp) + device->SetVertexShaderConstantF(0, (FLOAT*)&prg[active_index].mvp, 4); +} + +static bool load_program(unsigned index, const char *prog, bool path_is_file) +{ + bool ret, ret_fp, ret_vp; + ID3DXBuffer *listing_f = NULL; + ID3DXBuffer *listing_v = NULL; + ID3DXBuffer *code_f = NULL; + ID3DXBuffer *code_v = NULL; + + ret = true; + + if (path_is_file) + { + ret_fp = D3DXCompileShaderFromFile(prog, NULL, NULL, "main_fragment", "ps_2_0", 0, &code_f, &listing_f, NULL); + ret_vp = D3DXCompileShaderFromFile(prog, NULL, NULL, "main_vertex", "vs_2_0", 0, &code_v, &listing_v, NULL); + } + else + { + ret_fp = D3DXCompileShader(prog, sizeof(prog), NULL, NULL, "main_fragment", "ps_2_0", 0, &code_f, &listing_f, NULL ); + ret_vp = D3DXCompileShader(prog, sizeof(prog), NULL, NULL, "main_vertex", "vs_2_0", 0, &code_v, &listing_v, NULL ); + } + + if (FAILED(ret_fp) || FAILED(ret_vp)) + { + SSNES_ERR("HLSL error:\n"); + if(listing_f) + SSNES_ERR("Fragment:\n%s\n", (char*)listing_f->GetBufferPointer()); + if(listing_v) + SSNES_ERR("Vertex:\n%s\n", (char*)listing_v->GetBufferPointer()); + + ret = false; + goto end; + } + + prg[index].fprg = D3DDevice_CreatePixelShader((const DWORD*)code_f->GetBufferPointer()); + prg[index].vprg = D3DDevice_CreateVertexShader((const DWORD*)code_v->GetBufferPointer()); + code_f->Release(); + code_v->Release(); + +end: + free(listing_f); + free(listing_v); + return ret; +} + +static bool load_stock(void) +{ + if (!load_program(0, stock_hlsl_program, false)) + { + SSNES_ERR("Failed to compile passthrough shader, is something wrong with your environment?\n"); + return false; + } + + return true; +} + +static bool load_plain(const char *path) +{ + if (!load_stock()) + return false; + +#if 0 + SSNES_LOG("Loading HLSL file: %s\n", path); + + if (!load_program(1, path, true)) + return false; +#endif + + return true; +} + +static void hlsl_deinit_progs(void) +{ + D3DResource_Release((D3DResource *)vid->pPixelShader); + D3DResource_Release((D3DResource *)vid->pVertexShader); +} + +static void hlsl_deinit_state(void) +{ + hlsl_active = false; + + hlsl_deinit_progs(); +} + +bool hlsl_init(const char *path) +{ + if (strstr(path, ".cgp")) + { + if (!load_preset(path)) + return false; + } + else + { + if (!load_plain(path)) + return false; + } + + hlsl_active = true; + return true; +} + +void hlsl_use(IDirect3DDevice9 * device, unsigned index) +{ + if (hlsl_active && prg[index].vprg && prg[index].fprg) + { + active_index = index; + D3DDevice_SetVertexShader(device, prg[index].vprg); + D3DDevice_SetPixelShader(device, prg[index].fprg); + } +} + +// Full deinit. +void hlsl_deinit(void) +{ + if (!hlsl_active) + return; + + hlsl_deinit_state(); +} diff --git a/gfx/shader_hlsl.h b/gfx/shader_hlsl.h new file mode 100644 index 0000000000..2ff3fac88e --- /dev/null +++ b/gfx/shader_hlsl.h @@ -0,0 +1,34 @@ +/* SSNES - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * + * SSNES is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with SSNES. + * If not, see . + */ + + +#ifndef __SSNES_HLSL_H +#define __SSNES_HLSL_H + +#include + +bool hlsl_init(const char *path); + +void hlsl_deinit(void); + +void hlsl_set_proj_matrix(XMMATRIX rotation_value); + +void hlsl_set_params(IDirect3DDevice9 * device); + +void hlsl_use(IDirect3DDevice9 * device, unsigned index); + +#define SSNES_HLSL_MAX_SHADERS 16 + +#endif