Commits

spencercw committed 7f6b609

#45 Rewrite HLSL shaders in Cg.

Comments (0)

Files changed (8)

gb_emulator/gb_emulator.vcxproj

       <WarningLevel>Level4</WarningLevel>
       <Optimization>Disabled</Optimization>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>DEBUG;ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <LargeAddressAware>true</LargeAddressAware>
-      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x86;$(BOOST_ROOT)\lib;$(DIRECTX_SDK_ROOT)\Lib\x86</AdditionalLibraryDirectories>
-      <AdditionalDependencies>avrt.lib;d3d11.lib;d3dx11d.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x86;$(BOOST_ROOT)\lib;$(CG_LIB_PATH);$(DIRECTX_SDK_ROOT)\Lib\x86</AdditionalLibraryDirectories>
+      <AdditionalDependencies>avrt.lib;cg.lib;cgD3D11.lib;d3d11.lib;d3dx11d.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
     </Link>
     <PostBuildEvent>
       <WarningLevel>Level4</WarningLevel>
       <Optimization>Disabled</Optimization>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>DEBUG;ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <LargeAddressAware>true</LargeAddressAware>
-      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x64;$(BOOST_ROOT)\lib64;$(DIRECTX_SDK_ROOT)\Lib\x64</AdditionalLibraryDirectories>
-      <AdditionalDependencies>avrt.lib;d3d11.lib;d3dx11d.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x64;$(BOOST_ROOT)\lib64;$(CG_LIB64_PATH);$(DIRECTX_SDK_ROOT)\Lib\x64</AdditionalLibraryDirectories>
+      <AdditionalDependencies>avrt.lib;cg.lib;cgD3D11.lib;d3d11.lib;d3dx11d.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
     </Link>
     <PostBuildEvent>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <LargeAddressAware>true</LargeAddressAware>
-      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x86;$(BOOST_ROOT)\lib;$(DIRECTX_SDK_ROOT)\Lib\x86</AdditionalLibraryDirectories>
-      <AdditionalDependencies>avrt.lib;d3d11.lib;d3dx11.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x86;$(BOOST_ROOT)\lib;$(CG_LIB_PATH);$(DIRECTX_SDK_ROOT)\Lib\x86</AdditionalLibraryDirectories>
+      <AdditionalDependencies>avrt.lib;cg.lib;cgD3D11.lib;d3d11.lib;d3dx11.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
     </Link>
     <PostBuildEvent>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\libsndfile\include;$(SolutionDir)third_party\protobuf\src;$(SolutionDir)third_party\sdl\include;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <LargeAddressAware>true</LargeAddressAware>
-      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x64;$(BOOST_ROOT)\lib64;$(DIRECTX_SDK_ROOT)\Lib\x64</AdditionalLibraryDirectories>
-      <AdditionalDependencies>avrt.lib;d3d11.lib;d3dx11.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)third_party\libsndfile\x64;$(BOOST_ROOT)\lib64;$(CG_LIB64_PATH);$(DIRECTX_SDK_ROOT)\Lib\x64</AdditionalLibraryDirectories>
+      <AdditionalDependencies>avrt.lib;cg.lib;cgD3D11.lib;d3d11.lib;d3dx11.lib;dxgi.lib;hqx.lib;libprotobuf.lib;libsndfile-1.lib;sdl.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
     </Link>
     <PostBuildEvent>
     <None Include="gb_cpu_opcodes.cpp.inc" />
     <None Include="gb_disassembler_opcodes.cpp.inc" />
     <None Include="gen_ops.py" />
-    <None Include="shaders\pixel_shader.hlsl" />
-    <None Include="shaders\vertex_shader.hlsl" />
+    <None Include="shaders\pixel_shader.cg" />
+    <None Include="shaders\vertex_shader.cg" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

gb_emulator/gb_emulator.vcxproj.filters

     <None Include="gb_disassembler_opcodes.cpp.inc">
       <Filter>Source Files</Filter>
     </None>
-    <None Include="shaders\pixel_shader.hlsl">
+    <None Include="shaders\pixel_shader.cg">
       <Filter>Shader Files</Filter>
     </None>
-    <None Include="shaders\vertex_shader.hlsl">
+    <None Include="shaders\vertex_shader.cg">
       <Filter>Shader Files</Filter>
     </None>
   </ItemGroup>

gb_emulator/include/gb_emulator/gb_video_d3d11.h

 #include <stdint.h>
 
 #include <boost/filesystem/path.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <atlbase.h>
 #include <atlcom.h>
 
 #include <gb_emulator/gb_video.hpp>
 
+struct _CGcontext;
+struct _CGprogram;
+
 struct ID3D11Buffer;
 struct ID3D11Device;
 struct ID3D11DeviceContext;
 	ATL::CComPtr<IDXGISwapChain> swapChain_;
 	ATL::CComPtr<ID3D11RenderTargetView> renderTarget_;
 
-	ATL::CComPtr<ID3D11VertexShader> vertexShader_;
-	ATL::CComPtr<ID3D11PixelShader> pixelShader_;
-
 	ATL::CComPtr<ID3D11Buffer> vertexBuffer_;
 	ATL::CComPtr<ID3D11InputLayout> layout_;
 	ATL::CComPtr<ID3D11Texture2D> texture_;
-	ATL::CComPtr<ID3D11ShaderResourceView> textureShaderResource_;
-	ATL::CComPtr<ID3D11SamplerState> samplerState_;
+	ATL::CComPtr<ID3D11SamplerState> sampler_;
+
+	// Cg stuff
+	boost::shared_ptr<_CGcontext> cgContext_;
+	boost::shared_ptr<_CGprogram> vertexShader_;
+	boost::shared_ptr<_CGprogram> pixelShader_;
 
 	// Initialisation functions
 	void initPipeline(const boost::filesystem::path &installDir);

gb_emulator/shaders/pixel_shader.cg

+/*  Copyright � 2011 Chris Spencer <spencercw@gmail.com>
+
+    This program 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 Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+struct PixelInput
+{
+	float4 position : SV_POSITION;
+	float2 texCoord : TEXCOORD0;
+};
+
+float4 main(PixelInput input, uniform sampler2D sampler) : COLOR
+{
+	float4 colour = tex2D(sampler, input.texCoord);
+	colour[3] = 1.0;
+	return colour;
+}

gb_emulator/shaders/pixel_shader.hlsl

-Texture2D shaderTexture;
-SamplerState SampleType;
-
-struct PixelInput
-{
-	float4 position : SV_POSITION;
-	float2 tex : TEXCOORD0;
-};
-
-float4 main(PixelInput input) : SV_TARGET
-{
-	float4 colour = shaderTexture.Sample(SampleType, input.tex);
-	colour[3] = 1.0;
-	return colour;
-}

gb_emulator/shaders/vertex_shader.cg

+/*  Copyright � 2011 Chris Spencer <spencercw@gmail.com>
+
+    This program 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 Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+struct VertexInput
+{
+	float4 position : POSITION;
+	float2 texCoord : TEXCOORD0;
+};
+
+struct PixelInput
+{
+	float4 position : SV_POSITION;
+	float2 texCoord : TEXCOORD0;
+};
+
+PixelInput main(VertexInput input)
+{
+	PixelInput output;
+	output.position = input.position;
+	output.texCoord = input.texCoord;
+	return output;
+}

gb_emulator/shaders/vertex_shader.hlsl

-struct VertexInput
-{
-	float4 position : POSITION;
-	float2 tex : TEXCOORD0;
-};
-
-struct PixelInput
-{
-	float4 position : SV_POSITION;
-	float2 tex : TEXCOORD0;
-};
-
-PixelInput main(VertexInput input)
-{
-	PixelInput output;
-
-	output.position = input.position;
-	output.tex  = input.tex;
-
-	return output;
-}

gb_emulator/src/gb_video_d3d11.cpp

 #include <boost/lexical_cast.hpp>
 #include <boost/scoped_array.hpp>
 
+#include <Cg/cgD3D11.h>
+
 #ifdef _MSC_VER
 #pragma warning(push, 0)
 #endif
 #endif
 
 #include <D3D11.h>
-#include <D3DX11.h>
 
 #include <gb_emulator/gb.hpp>
 
 namespace fs = boost::filesystem;
 using boost::lexical_cast;
 using boost::scoped_array;
+using boost::shared_ptr;
 using std::runtime_error;
 using std::string;
 
 
 void GbVideoD3D11::initPipeline(const fs::path &installDir)
 {
-	// Load the shaders
-	fs::path vertexShaderPath = installDir / L"shaders/vertex_shader.hlsl";
-	fs::path pixelShaderPath  = installDir / L"shaders/pixel_shader.hlsl";
+	// Initialise Cg
+	cgContext_.reset(cgCreateContext(), cgDestroyContext);
+	if (!cgContext_)
+	{
+		throw runtime_error(string("failed to create Cg context: ") + cgGetLastErrorString(NULL));
+	}
+
+	// Compile the shaders
+	fs::path vertexShaderPath = installDir / L"shaders/vertex_shader.cg";
+	fs::path pixelShaderPath  = installDir / L"shaders/pixel_shader.cg";
 	vertexShaderPath.make_preferred();
 	pixelShaderPath.make_preferred();
+	
+	string vertexShaderPathStr = vertexShaderPath.string();
+	string pixelShaderPathStr  = pixelShaderPath.string();
 
-	ID3D10Blob *vertexShaderBlob;
-	HRESULT hr = D3DX11CompileFromFile(vertexShaderPath.native().c_str(), NULL, NULL, "main",
-		"vs_5_0", 0, 0, NULL, &vertexShaderBlob, NULL, NULL);
+	vertexShader_.reset(cgCreateProgramFromFile(cgContext_.get(), CG_SOURCE,
+		vertexShaderPathStr.c_str(), CG_PROFILE_VS_5_0, NULL, NULL), cgDestroyProgram);
+	if (!vertexShader_)
+	{
+		throw runtime_error(string("failed to compile vertex shader: ") +
+			cgGetLastErrorString(NULL));
+	}
+
+	pixelShader_.reset(cgCreateProgramFromFile(cgContext_.get(), CG_SOURCE,
+		pixelShaderPathStr.c_str(), CG_PROFILE_PS_5_0, NULL, NULL), cgDestroyProgram);
+	if (!pixelShader_)
+	{
+		throw runtime_error(string("failed to compile pixel shader: ") +
+			cgGetLastErrorString(NULL));
+	}
+
+	// Load the shaders into Direct3D
+	HRESULT hr = cgD3D11SetDevice(cgContext_.get(), device_);
+	if (FAILED(hr))
+	{
+		throw runtime_error("failed to set Direct3D device within Cg: " + lexical_cast<string>(hr));
+	}
+
+	hr = cgD3D11LoadProgram(vertexShader_.get(), 0);
 	if (FAILED(hr))
 	{
 		throw runtime_error("failed to load vertex shader: " + lexical_cast<string>(hr));
 	}
 
-	ID3D10Blob *pixelShaderBlob;
-	hr = D3DX11CompileFromFile(pixelShaderPath.native().c_str(), NULL, NULL, "main", "ps_5_0", 0, 0,
-		NULL, &pixelShaderBlob, NULL, NULL);
+	hr = cgD3D11LoadProgram(pixelShader_.get(), 0);
 	if (FAILED(hr))
 	{
 		throw runtime_error("failed to load pixel shader: " + lexical_cast<string>(hr));
 	}
 
-	// Create the shader objects
-	hr = device_->CreateVertexShader(vertexShaderBlob->GetBufferPointer(),
-		vertexShaderBlob->GetBufferSize(), NULL, &vertexShader_);
-	if (FAILED(hr))
+	// Get the blobs
+	ID3D10Blob *vertexShaderBlob = cgD3D11GetCompiledProgram(vertexShader_.get());
+	if (!vertexShaderBlob)
 	{
-		throw runtime_error("failed to create vertex shader: " + lexical_cast<string>(hr));
+		throw runtime_error("failed to retrieve compiled vertex shader: " +
+			lexical_cast<string>(cgD3D11GetLastError()));
 	}
 
-	hr = device_->CreatePixelShader(pixelShaderBlob->GetBufferPointer(),
-		pixelShaderBlob->GetBufferSize(), NULL, &pixelShader_);
-	if (FAILED(hr))
+	ID3D10Blob *pixelShaderBlob  = cgD3D11GetCompiledProgram(pixelShader_.get());
+	if (!pixelShaderBlob)
 	{
-		throw runtime_error("failed to create pixel shader: " + lexical_cast<string>(hr));
+		throw runtime_error("failed to retrieve compiled pixel shader: " +
+			lexical_cast<string>(cgD3D11GetLastError()));
 	}
 
-	// Set the active shaders
-	deviceContext_->VSSetShader(vertexShader_, NULL, 0);
-	deviceContext_->PSSetShader(pixelShader_, NULL, 0);
-	deviceContext_->PSSetSamplers(0, 1, &samplerState_.p);
-
 	// Create the input layout descriptor
 	D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[] = {
 		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT,
 
 	deviceContext_->IASetInputLayout(layout_);
 
-	// Create the texture sampler descriptor
+	// Create the texture sampler
 	D3D11_SAMPLER_DESC samplerDesc;
 	memset(&samplerDesc, 0, sizeof(samplerDesc));
 	samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
 	samplerDesc.MinLOD = 0.0f;
 	samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
 
-	hr = device_->CreateSamplerState(&samplerDesc, &samplerState_);
+	hr = device_->CreateSamplerState(&samplerDesc, &sampler_);
 	if (FAILED(hr))
 	{
 		throw runtime_error("failed to create sampler state: " + lexical_cast<string>(hr));
 		throw runtime_error("failed to create texture: " + lexical_cast<string>(hr));
 	}
 
-	// Create the shader resource for the texture
-	hr = device_->CreateShaderResourceView(texture_, NULL, &textureShaderResource_);
+	// Bind the texture and sampler to the shader
+	shared_ptr<_CGparameter> samplerParam(cgGetNamedParameter(pixelShader_.get(), "sampler"),
+		cgDestroyParameter);
+	if (!samplerParam)
+	{
+		throw runtime_error(string("failed to get pixel shader sampler parameter: ") +
+			cgGetLastErrorString(NULL));
+	}
+
+	cgD3D11SetTextureSamplerStateParameter(samplerParam.get(), texture_, sampler_);
+
+	// Bind the shaders
+	hr = cgD3D11BindProgram(vertexShader_.get());
 	if (FAILED(hr))
 	{
-		throw runtime_error("failed to create shader resource for texture: " +
-			lexical_cast<string>(hr));
+		throw runtime_error("failed to bind vertex shader: " + lexical_cast<string>(hr));
+	}
+
+	hr = cgD3D11BindProgram(pixelShader_.get());
+	if (FAILED(hr))
+	{
+		throw runtime_error("failed to bind pixel shader: " + lexical_cast<string>(hr));
 	}
 }
 
 	static const UINT offset = 0;
 	deviceContext_->IASetVertexBuffers(0, 1, &vertexBuffer_.p, &stride, &offset);
 
-	// Set the texture
-	deviceContext_->PSSetShaderResources(0, 1, &textureShaderResource_.p);
-
 	// Draw the vertices to the back buffer
 	deviceContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
 	deviceContext_->Draw(5, 0);