DX11: Support thick lines and large points with geometry shaders. Lines still aren't drawn with correct thickness, see Twilight Princess map. But the map corners are drawn with correct shadow "blobs" for the first time!

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7340 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Nolan Check 2011-03-14 09:38:29 +00:00
parent 8fedc3db38
commit 7c536b8f15
19 changed files with 1982 additions and 720 deletions

View File

@ -73,6 +73,37 @@ static char text[16384];
#define WRITE p+=sprintf #define WRITE p+=sprintf
char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE api_type)
{
WRITE(p, "struct VS_OUTPUT {\n");
WRITE(p, " float4 pos : POSITION;\n");
WRITE(p, " float4 colors_0 : COLOR0;\n");
WRITE(p, " float4 colors_1 : COLOR1;\n");
if (xfregs.numTexGen.numTexGens < 7) {
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
WRITE(p, " float3 tex%d : TEXCOORD%d;\n", i, i);
WRITE(p, " float4 clipPos : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens);
if(g_ActiveConfig.bEnablePixelLigting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
WRITE(p, " float4 Normal : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens + 1);
} else {
// clip position is in w of first 4 texcoords
if(g_ActiveConfig.bEnablePixelLigting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
{
for (int i = 0; i < 8; ++i)
WRITE(p, " float4 tex%d : TEXCOORD%d;\n", i, i);
}
else
{
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
WRITE(p, " float%d tex%d : TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, i);
}
}
WRITE(p, "};\n");
return p;
}
const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type) const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
{ {
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
@ -102,31 +133,7 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
"typedef struct { float4 T0, T1, T2, T3; } s_"I_PROJECTION";\n" "typedef struct { float4 T0, T1, T2, T3; } s_"I_PROJECTION";\n"
); );
WRITE(p, "struct VS_OUTPUT {\n"); p = GenerateVSOutputStruct(p, components, api_type);
WRITE(p, " float4 pos : POSITION;\n");
WRITE(p, " float4 colors_0 : COLOR0;\n");
WRITE(p, " float4 colors_1 : COLOR1;\n");
if (xfregs.numTexGen.numTexGens < 7) {
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
WRITE(p, " float3 tex%d : TEXCOORD%d;\n", i, i);
WRITE(p, " float4 clipPos : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens);
if(g_ActiveConfig.bEnablePixelLigting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
WRITE(p, " float4 Normal : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens + 1);
} else {
// clip position is in w of first 4 texcoords
if(g_ActiveConfig.bEnablePixelLigting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
{
for (int i = 0; i < 8; ++i)
WRITE(p, " float4 tex%d : TEXCOORD%d;\n", i, i);
}
else
{
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
WRITE(p, " float%d tex%d : TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, i);
}
}
WRITE(p, "};\n");
// uniforms // uniforms

View File

@ -103,6 +103,7 @@ public:
// components is included in the uid. // components is included in the uid.
char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE api_type);
const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type); const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type);
void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components); void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components);

View File

@ -197,9 +197,11 @@
<ClCompile Include="Src\D3DUtil.cpp" /> <ClCompile Include="Src\D3DUtil.cpp" />
<ClCompile Include="Src\FramebufferManager.cpp" /> <ClCompile Include="Src\FramebufferManager.cpp" />
<ClCompile Include="Src\GfxState.cpp" /> <ClCompile Include="Src\GfxState.cpp" />
<ClCompile Include="Src\LineGeometryShader.cpp" />
<ClCompile Include="Src\main.cpp" /> <ClCompile Include="Src\main.cpp" />
<ClCompile Include="Src\NativeVertexFormat.cpp" /> <ClCompile Include="Src\NativeVertexFormat.cpp" />
<ClCompile Include="Src\PixelShaderCache.cpp" /> <ClCompile Include="Src\PixelShaderCache.cpp" />
<ClCompile Include="Src\PointGeometryShader.cpp" />
<ClCompile Include="Src\PSTextureEncoder.cpp" /> <ClCompile Include="Src\PSTextureEncoder.cpp" />
<ClCompile Include="Src\Render.cpp" /> <ClCompile Include="Src\Render.cpp" />
<ClCompile Include="Src\stdafx.cpp"> <ClCompile Include="Src\stdafx.cpp">
@ -225,8 +227,10 @@
<ClInclude Include="Src\FramebufferManager.h" /> <ClInclude Include="Src\FramebufferManager.h" />
<ClInclude Include="Src\GfxState.h" /> <ClInclude Include="Src\GfxState.h" />
<ClInclude Include="Src\Globals.h" /> <ClInclude Include="Src\Globals.h" />
<ClInclude Include="Src\LineGeometryShader.h" />
<ClInclude Include="Src\main.h" /> <ClInclude Include="Src\main.h" />
<ClInclude Include="Src\PixelShaderCache.h" /> <ClInclude Include="Src\PixelShaderCache.h" />
<ClInclude Include="Src\PointGeometryShader.h" />
<ClInclude Include="Src\PSTextureEncoder.h" /> <ClInclude Include="Src\PSTextureEncoder.h" />
<ClInclude Include="Src\Render.h" /> <ClInclude Include="Src\Render.h" />
<ClInclude Include="Src\stdafx.h" /> <ClInclude Include="Src\stdafx.h" />

View File

@ -51,6 +51,12 @@
<ClCompile Include="Src\Television.cpp"> <ClCompile Include="Src\Television.cpp">
<Filter>Render</Filter> <Filter>Render</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Src\LineGeometryShader.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="Src\PointGeometryShader.cpp">
<Filter>Render</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Src\Globals.h" /> <ClInclude Include="Src\Globals.h" />
@ -105,6 +111,12 @@
<ClInclude Include="Src\Television.h"> <ClInclude Include="Src\Television.h">
<Filter>Render</Filter> <Filter>Render</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Src\LineGeometryShader.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="Src\PointGeometryShader.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="D3D"> <Filter Include="D3D">

View File

@ -415,7 +415,6 @@ void Close()
UnloadDXGI(); UnloadDXGI();
} }
/* just returning the 4_0 ones here */
const char* VertexShaderVersionString() const char* VertexShaderVersionString()
{ {
if(featlevel == D3D_FEATURE_LEVEL_11_0) return "vs_5_0"; if(featlevel == D3D_FEATURE_LEVEL_11_0) return "vs_5_0";
@ -423,6 +422,13 @@ const char* VertexShaderVersionString()
else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "vs_4_0"; else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "vs_4_0";
} }
const char* GeometryShaderVersionString()
{
if(featlevel == D3D_FEATURE_LEVEL_11_0) return "gs_5_0";
else if(featlevel == D3D_FEATURE_LEVEL_10_1) return "gs_4_1";
else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "gs_4_0";
}
const char* PixelShaderVersionString() const char* PixelShaderVersionString()
{ {
if(featlevel == D3D_FEATURE_LEVEL_11_0) return "ps_5_0"; if(featlevel == D3D_FEATURE_LEVEL_11_0) return "ps_5_0";

View File

@ -64,6 +64,7 @@ unsigned int GetBackBufferWidth();
unsigned int GetBackBufferHeight(); unsigned int GetBackBufferHeight();
D3DTexture2D* &GetBackBuffer(); D3DTexture2D* &GetBackBuffer();
const char* PixelShaderVersionString(); const char* PixelShaderVersionString();
const char* GeometryShaderVersionString();
const char* VertexShaderVersionString(); const char* VertexShaderVersionString();
bool BGRATexturesSupported(); bool BGRATexturesSupported();

View File

@ -82,6 +82,61 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
// bytecode->shader
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len)
{
ID3D11GeometryShader* g_shader;
HRESULT hr = D3D::device->CreateGeometryShader(bytecode, len, NULL, &g_shader);
if (FAILED(hr))
{
PanicAlert("CreateGeometryShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__);
g_shader = NULL;
}
return g_shader;
}
// code->bytecode
bool CompileGeometryShader(const char* code, unsigned int len, D3DBlob** blob,
const D3D_SHADER_MACRO* pDefines)
{
ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
#endif
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, pDefines, NULL, "main", D3D::GeometryShaderVersionString(),
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (errorBuffer)
{
INFO_LOG(VIDEO, "Geometry shader compiler messages:\n%s\n",
(const char*)errorBuffer->GetBufferPointer());
}
if (FAILED(hr))
{
if (g_ActiveConfig.bShowShaderErrors)
{
std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling geometry shader", MB_ICONERROR);
}
*blob = NULL;
errorBuffer->Release();
}
else
{
*blob = new D3DBlob(shaderBuffer);
shaderBuffer->Release();
}
return SUCCEEDED(hr);
}
// bytecode->shader // bytecode->shader
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len) ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len)
{ {
@ -138,7 +193,8 @@ bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob,
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len) ID3D11VertexShader* CompileAndCreateVertexShader(const char* code,
unsigned int len)
{ {
D3DBlob* blob = NULL; D3DBlob* blob = NULL;
if (CompileVertexShader(code, len, &blob)) if (CompileVertexShader(code, len, &blob))
@ -151,7 +207,22 @@ ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int
return NULL; return NULL;
} }
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len) ID3D11GeometryShader* CompileAndCreateGeometryShader(const char* code,
unsigned int len, const D3D_SHADER_MACRO* pDefines)
{
D3DBlob* blob = NULL;
if (CompileGeometryShader(code, len, &blob, pDefines))
{
ID3D11GeometryShader* g_shader = CreateGeometryShaderFromByteCode(blob);
blob->Release();
return g_shader;
}
PanicAlert("Failed to compile and create geometry shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
return NULL;
}
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code,
unsigned int len)
{ {
D3DBlob* blob = NULL; D3DBlob* blob = NULL;
CompilePixelShader(code, len, &blob); CompilePixelShader(code, len, &blob);

View File

@ -29,20 +29,38 @@ namespace DX11
namespace D3D namespace D3D
{ {
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len); ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len);
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len);
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len); ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len);
// The returned bytecode buffers should be Release()d. // The returned bytecode buffers should be Release()d.
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob); bool CompileVertexShader(const char* code, unsigned int len,
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = NULL); D3DBlob** blob);
bool CompileGeometryShader(const char* code, unsigned int len,
D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = NULL);
bool CompilePixelShader(const char* code, unsigned int len,
D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = NULL);
// Utility functions // Utility functions
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len); ID3D11VertexShader* CompileAndCreateVertexShader(const char* code,
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len); unsigned int len);
ID3D11GeometryShader* CompileAndCreateGeometryShader(const char* code,
unsigned int len, const D3D_SHADER_MACRO* pDefines = NULL);
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code,
unsigned int len);
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) { return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); } inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode)
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); } { return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); } inline ID3D11GeometryShader* CreateGeometryShaderFromByteCode(D3DBlob* bytecode)
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); } { return CreateGeometryShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode)
{ return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code)
{ return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); }
inline ID3D11GeometryShader* CompileAndCreateGeometryShader(D3DBlob* code, const D3D_SHADER_MACRO* pDefines = NULL)
{ return CompileAndCreateGeometryShader((const char*)code->Data(), code->Size(), pDefines); }
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code)
{ return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); }
} }
} // namespace DX11 } // namespace DX11

View File

@ -0,0 +1,452 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "LineGeometryShader.h"
#include <sstream>
#include "D3DBase.h"
#include "D3DShader.h"
#include "VertexShaderGen.h"
namespace DX11
{
union LineGSParams
{
struct
{
FLOAT LineWidth; // In units of 1/6 of an EFB pixel
FLOAT TexOffset;
};
// Constant buffers must be a multiple of 16 bytes in size.
u8 pad[16]; // Pad to the next multiple of 16 bytes
};
static const char LINE_GS_COMMON[] =
// The struct VS_OUTPUT used by the vertex shader goes here.
"// dolphin-emu line geometry shader common part\n"
"cbuffer cbParams : register(b0)\n"
"{\n"
"struct\n" // Should match LineGSParams above
"{\n"
"float LineWidth;\n"
"float TexOffset;\n"
"} Params;\n"
"}\n"
"[maxvertexcount(4)]\n"
"void main(line VS_OUTPUT input[2], inout TriangleStream<VS_OUTPUT> outStream)\n"
"{\n"
// Pretend input[0] is on the bottom and input[1] is on top.
// We generate vertices to the left and right.
// Correct w coordinate so screen-space math will work
"VS_OUTPUT l0 = input[0];\n"
"l0.pos /= l0.pos.w;\n"
"VS_OUTPUT r0 = l0;\n"
"VS_OUTPUT l1 = input[1];\n"
"l1.pos /= l1.pos.w;\n"
"VS_OUTPUT r1 = l1;\n"
// GameCube/Wii's line drawing algorithm is a little quirky. It does not
// use the correct line caps. Instead, the line caps are vertical or
// horizontal depending the slope of the line.
"float2 offset;\n"
"float2 to = input[1].pos.xy - input[0].pos.xy;\n"
// FIXME: What does real hardware do when line is at a 45-degree angle?
// FIXME: Lines aren't drawn at the correct width. See Twilight Princess map.
"if (abs(to.y) > abs(to.x)) {\n"
// Line is more tall. Extend geometry left and right.
// Lerp Params.LineWidth/2 from [0..640] to [-1..1]
"offset = float2(Params.LineWidth/640, 0);\n"
"} else {\n"
// Line is more wide. Extend geometry up and down.
// Lerp Params.LineWidth/2 from [0..528] to [1..-1]
"offset = float2(0, -Params.LineWidth/528);\n"
"}\n"
"l0.pos.xy -= offset;\n"
"r0.pos.xy += offset;\n"
"l1.pos.xy -= offset;\n"
"r1.pos.xy += offset;\n"
"#ifndef NUM_TEXCOORDS\n"
"#error NUM_TEXCOORDS not defined\n"
"#endif\n"
// Apply TexOffset to all tex coordinates in the vertex
"#if NUM_TEXCOORDS >= 1\n"
"r0.tex0.x += Params.TexOffset;\n"
"r1.tex0.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 2\n"
"r0.tex1.x += Params.TexOffset;\n"
"r1.tex1.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 3\n"
"r0.tex2.x += Params.TexOffset;\n"
"r1.tex2.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 4\n"
"r0.tex3.x += Params.TexOffset;\n"
"r1.tex3.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 5\n"
"r0.tex4.x += Params.TexOffset;\n"
"r1.tex4.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 6\n"
"r0.tex5.x += Params.TexOffset;\n"
"r1.tex5.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 7\n"
"r0.tex6.x += Params.TexOffset;\n"
"r1.tex6.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 8\n"
"r0.tex7.x += Params.TexOffset;\n"
"r1.tex7.x += Params.TexOffset;\n"
"#endif\n"
"outStream.Append(l0);\n"
"outStream.Append(r0);\n"
"outStream.Append(l1);\n"
"outStream.Append(r1);\n"
"}\n"
;
LineGeometryShader::LineGeometryShader()
: m_ready(false), m_paramsBuffer(NULL)
{ }
void LineGeometryShader::Init()
{
m_ready = false;
HRESULT hr;
// Create constant buffer for uploading data to geometry shader
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams),
D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_paramsBuffer);
CHECK(SUCCEEDED(hr), "create line geometry shader params buffer");
D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer");
m_ready = true;
}
void LineGeometryShader::Shutdown()
{
m_ready = false;
for (ComboMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_shaders.clear();
SAFE_RELEASE(m_paramsBuffer);
}
bool LineGeometryShader::SetShader(u32 components, float lineWidth, float texOffset)
{
if (!m_ready)
return false;
// Make sure geometry shader for "components" is available
ComboMap::iterator shaderIt = m_shaders.find(components);
if (shaderIt == m_shaders.end())
{
// Generate new shader. Warning: not thread-safe.
static char code[16384];
char* p = code;
p = GenerateVSOutputStruct(p, components, API_D3D11);
p += sprintf(p, "\n%s", LINE_GS_COMMON);
std::stringstream numTexCoordsStr;
numTexCoordsStr << xfregs.numTexGen.numTexGens;
INFO_LOG(VIDEO, "Compiling line geometry shader for components 0x%.08X (num texcoords %d)",
components, xfregs.numTexGen.numTexGens);
D3D_SHADER_MACRO macros[] = {
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ NULL, NULL }
};
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
if (!newShader)
{
WARN_LOG(VIDEO, "Line geometry shader for components 0x%.08X failed to compile", components);
// Add dummy shader to prevent trying to compile again
m_shaders[components] = NULL;
return false;
}
shaderIt = m_shaders.insert(std::make_pair(components, newShader)).first;
}
if (shaderIt != m_shaders.end())
{
if (shaderIt->second)
{
LineGSParams params = { 0 };
params.LineWidth = lineWidth;
params.TexOffset = texOffset;
D3D::context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0);
D3D::context->GSSetShader(shaderIt->second, NULL, 0);
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
return true;
}
else
return false;
}
else
return false;
}
}
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "LineGeometryShader.h"
#include <sstream>
#include "D3DBase.h"
#include "D3DShader.h"
#include "VertexShaderGen.h"
namespace DX11
{
union LineGSParams
{
struct
{
FLOAT LineWidth; // In units of 1/6 of an EFB pixel
FLOAT TexOffset;
};
// Constant buffers must be a multiple of 16 bytes in size.
u8 pad[16]; // Pad to the next multiple of 16 bytes
};
static const char LINE_GS_COMMON[] =
// The struct VS_OUTPUT used by the vertex shader goes here.
"// dolphin-emu line geometry shader common part\n"
"cbuffer cbParams : register(b0)\n"
"{\n"
"struct\n" // Should match LineGSParams above
"{\n"
"float LineWidth;\n"
"float TexOffset;\n"
"} Params;\n"
"}\n"
"[maxvertexcount(4)]\n"
"void main(line VS_OUTPUT input[2], inout TriangleStream<VS_OUTPUT> outStream)\n"
"{\n"
// Pretend input[0] is on the bottom and input[1] is on top.
// We generate vertices to the left and right.
// Correct w coordinate so screen-space math will work
"VS_OUTPUT l0 = input[0];\n"
"l0.pos /= l0.pos.w;\n"
"VS_OUTPUT r0 = l0;\n"
"VS_OUTPUT l1 = input[1];\n"
"l1.pos /= l1.pos.w;\n"
"VS_OUTPUT r1 = l1;\n"
// GameCube/Wii's line drawing algorithm is a little quirky. It does not
// use the correct line caps. Instead, the line caps are vertical or
// horizontal depending the slope of the line.
"float2 offset;\n"
"float2 to = input[1].pos.xy - input[0].pos.xy;\n"
// FIXME: What does real hardware do when line is at a 45-degree angle?
// FIXME: Lines aren't drawn at the correct width. See Twilight Princess map.
"if (abs(to.y) > abs(to.x)) {\n"
// Line is more tall. Extend geometry left and right.
// Lerp Params.LineWidth/2 from [0..640] to [-1..1]
"offset = float2(Params.LineWidth/640, 0);\n"
"} else {\n"
// Line is more wide. Extend geometry up and down.
// Lerp Params.LineWidth/2 from [0..528] to [1..-1]
"offset = float2(0, -Params.LineWidth/528);\n"
"}\n"
"l0.pos.xy -= offset;\n"
"r0.pos.xy += offset;\n"
"l1.pos.xy -= offset;\n"
"r1.pos.xy += offset;\n"
"#ifndef NUM_TEXCOORDS\n"
"#error NUM_TEXCOORDS not defined\n"
"#endif\n"
// Apply TexOffset to all tex coordinates in the vertex
"#if NUM_TEXCOORDS >= 1\n"
"r0.tex0.x += Params.TexOffset;\n"
"r1.tex0.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 2\n"
"r0.tex1.x += Params.TexOffset;\n"
"r1.tex1.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 3\n"
"r0.tex2.x += Params.TexOffset;\n"
"r1.tex2.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 4\n"
"r0.tex3.x += Params.TexOffset;\n"
"r1.tex3.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 5\n"
"r0.tex4.x += Params.TexOffset;\n"
"r1.tex4.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 6\n"
"r0.tex5.x += Params.TexOffset;\n"
"r1.tex5.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 7\n"
"r0.tex6.x += Params.TexOffset;\n"
"r1.tex6.x += Params.TexOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 8\n"
"r0.tex7.x += Params.TexOffset;\n"
"r1.tex7.x += Params.TexOffset;\n"
"#endif\n"
"outStream.Append(l0);\n"
"outStream.Append(r0);\n"
"outStream.Append(l1);\n"
"outStream.Append(r1);\n"
"}\n"
;
LineGeometryShader::LineGeometryShader()
: m_ready(false), m_paramsBuffer(NULL)
{ }
void LineGeometryShader::Init()
{
m_ready = false;
HRESULT hr;
// Create constant buffer for uploading data to geometry shader
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams),
D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_paramsBuffer);
CHECK(SUCCEEDED(hr), "create line geometry shader params buffer");
D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer");
m_ready = true;
}
void LineGeometryShader::Shutdown()
{
m_ready = false;
for (ComboMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_shaders.clear();
SAFE_RELEASE(m_paramsBuffer);
}
bool LineGeometryShader::SetShader(u32 components, float lineWidth, float texOffset)
{
if (!m_ready)
return false;
// Make sure geometry shader for "components" is available
ComboMap::iterator shaderIt = m_shaders.find(components);
if (shaderIt == m_shaders.end())
{
// Generate new shader. Warning: not thread-safe.
static char code[16384];
char* p = code;
p = GenerateVSOutputStruct(p, components, API_D3D11);
p += sprintf(p, "\n%s", LINE_GS_COMMON);
std::stringstream numTexCoordsStr;
numTexCoordsStr << xfregs.numTexGen.numTexGens;
INFO_LOG(VIDEO, "Compiling line geometry shader for components 0x%.08X (num texcoords %d)",
components, xfregs.numTexGen.numTexGens);
D3D_SHADER_MACRO macros[] = {
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ NULL, NULL }
};
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
if (!newShader)
{
WARN_LOG(VIDEO, "Line geometry shader for components 0x%.08X failed to compile", components);
// Add dummy shader to prevent trying to compile again
m_shaders[components] = NULL;
return false;
}
shaderIt = m_shaders.insert(std::make_pair(components, newShader)).first;
}
if (shaderIt != m_shaders.end())
{
if (shaderIt->second)
{
LineGSParams params = { 0 };
params.LineWidth = lineWidth;
params.TexOffset = texOffset;
D3D::context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0);
D3D::context->GSSetShader(shaderIt->second, NULL, 0);
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
return true;
}
else
return false;
}
else
return false;
}
}

View File

@ -0,0 +1,114 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _LINEGEOMETRYSHADER_H
#define _LINEGEOMETRYSHADER_H
#include "VideoCommon.h"
struct ID3D11Buffer;
struct ID3D11GeometryShader;
namespace DX11
{
// This class manages a collection of line geometry shaders, one for each
// vertex format.
class LineGeometryShader
{
public:
LineGeometryShader();
void Init();
void Shutdown();
// Returns true on success, false on failure
bool SetShader(u32 components, float lineWidth, float texOffset);
private:
bool m_ready;
ID3D11Buffer* m_paramsBuffer;
typedef std::map<u32, ID3D11GeometryShader*> ComboMap;
ComboMap m_shaders;
};
}
#endif
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _LINEGEOMETRYSHADER_H
#define _LINEGEOMETRYSHADER_H
#include "VideoCommon.h"
struct ID3D11Buffer;
struct ID3D11GeometryShader;
namespace DX11
{
// This class manages a collection of line geometry shaders, one for each
// vertex format.
class LineGeometryShader
{
public:
LineGeometryShader();
void Init();
void Shutdown();
// Returns true on success, false on failure
bool SetShader(u32 components, float lineWidth, float texOffset);
private:
bool m_ready;
ID3D11Buffer* m_paramsBuffer;
typedef std::map<u32, ID3D11GeometryShader*> ComboMap;
ComboMap m_shaders;
};
}
#endif

View File

@ -1265,10 +1265,8 @@ bool PSTextureEncoder::SetStaticShader(unsigned int dstFormat, unsigned int srcF
HRESULT hr = D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), NULL, &newShader); HRESULT hr = D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), NULL, &newShader);
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader"); CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
m_staticShaders[key] = newShader; it = m_staticShaders.insert(std::make_pair(key, newShader)).first;
bytecode->Release(); bytecode->Release();
it = m_staticShaders.find(key);
} }
if (it != m_staticShaders.end()) if (it != m_staticShaders.end())

View File

@ -0,0 +1,434 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "PointGeometryShader.h"
#include <sstream>
#include "D3DBase.h"
#include "D3DShader.h"
#include "VertexShaderGen.h"
namespace DX11
{
union PointGSParams
{
struct
{
FLOAT PointSize; // In units of 1/6 of an EFB pixel
FLOAT TexOffset;
};
// Constant buffers must be a multiple of 16 bytes in size.
u8 pad[16]; // Pad to the next multiple of 16 bytes
};
static const char POINT_GS_COMMON[] =
// The struct VS_OUTPUT used by the vertex shader goes here.
"// dolphin-emu point geometry shader common part\n"
"cbuffer cbParams : register(b0)\n"
"{\n"
"struct\n" // Should match PointGSParams above
"{\n"
"float PointSize;\n"
"float TexOffset;\n"
"} Params;\n"
"}\n"
"[maxvertexcount(4)]\n"
"void main(point VS_OUTPUT input[1], inout TriangleStream<VS_OUTPUT> outStream)\n"
"{\n"
// Correct w coordinate so screen-space math will work
"VS_OUTPUT ptLL = input[0];\n"
"ptLL.pos /= ptLL.pos.w;\n"
"VS_OUTPUT ptLR = ptLL;\n"
"VS_OUTPUT ptUL = ptLL;\n"
"VS_OUTPUT ptUR = ptLL;\n"
// Distance from center to upper right vertex
"float2 offset = float2(Params.PointSize/640, -Params.PointSize/528);\n"
"ptLL.pos.xy += float2(-1,-1) * offset;\n"
"ptLR.pos.xy += float2(1,-1) * offset;\n"
"ptUL.pos.xy += float2(-1,1) * offset;\n"
"ptUR.pos.xy += offset;\n"
"float2 texOffset = float2(Params.TexOffset, Params.TexOffset);\n"
"#ifndef NUM_TEXCOORDS\n"
"#error NUM_TEXCOORDS not defined\n"
"#endif\n"
// Apply TexOffset to all tex coordinates in the vertex
"#if NUM_TEXCOORDS >= 1\n"
"ptLL.tex0.xy += float2(0,1) * texOffset;\n"
"ptLR.tex0.xy += texOffset;\n"
"ptUR.tex0.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 2\n"
"ptLL.tex1.xy += float2(0,1) * texOffset;\n"
"ptLR.tex1.xy += texOffset;\n"
"ptUR.tex1.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 3\n"
"ptLL.tex2.xy += float2(0,1) * texOffset;\n"
"ptLR.tex2.xy += texOffset;\n"
"ptUR.tex2.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 4\n"
"ptLL.tex3.xy += float2(0,1) * texOffset;\n"
"ptLR.tex3.xy += texOffset;\n"
"ptUR.tex3.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 5\n"
"ptLL.tex4.xy += float2(0,1) * texOffset;\n"
"ptLR.tex4.xy += texOffset;\n"
"ptUR.tex4.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 6\n"
"ptLL.tex5.xy += float2(0,1) * texOffset;\n"
"ptLR.tex5.xy += texOffset;\n"
"ptUR.tex5.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 7\n"
"ptLL.tex6.xy += float2(0,1) * texOffset;\n"
"ptLR.tex6.xy += texOffset;\n"
"ptUR.tex6.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 8\n"
"ptLL.tex7.xy += float2(0,1) * texOffset;\n"
"ptLR.tex7.xy += texOffset;\n"
"ptUR.tex7.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"outStream.Append(ptLL);\n"
"outStream.Append(ptLR);\n"
"outStream.Append(ptUL);\n"
"outStream.Append(ptUR);\n"
"}\n"
;
PointGeometryShader::PointGeometryShader()
: m_ready(false), m_paramsBuffer(NULL)
{ }
void PointGeometryShader::Init()
{
m_ready = false;
HRESULT hr;
// Create constant buffer for uploading data to geometry shader
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams),
D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_paramsBuffer);
CHECK(SUCCEEDED(hr), "create point geometry shader params buffer");
D3D::SetDebugObjectName(m_paramsBuffer, "point geometry shader params buffer");
m_ready = true;
}
void PointGeometryShader::Shutdown()
{
m_ready = false;
for (ComboMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_shaders.clear();
SAFE_RELEASE(m_paramsBuffer);
}
bool PointGeometryShader::SetShader(u32 components, float pointSize, float texOffset)
{
if (!m_ready)
return false;
// Make sure geometry shader for "components" is available
ComboMap::iterator shaderIt = m_shaders.find(components);
if (shaderIt == m_shaders.end())
{
// Generate new shader. Warning: not thread-safe.
static char code[16384];
char* p = code;
p = GenerateVSOutputStruct(p, components, API_D3D11);
p += sprintf(p, "\n%s", POINT_GS_COMMON);
std::stringstream numTexCoordsStr;
numTexCoordsStr << xfregs.numTexGen.numTexGens;
INFO_LOG(VIDEO, "Compiling point geometry shader for components 0x%.08X (num texcoords %d)",
components, xfregs.numTexGen.numTexGens);
D3D_SHADER_MACRO macros[] = {
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ NULL, NULL }
};
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
if (!newShader)
{
WARN_LOG(VIDEO, "Point geometry shader for components 0x%.08X failed to compile", components);
// Add dummy shader to prevent trying to compile again
m_shaders[components] = NULL;
return false;
}
shaderIt = m_shaders.insert(std::make_pair(components, newShader)).first;
}
if (shaderIt != m_shaders.end())
{
if (shaderIt->second)
{
PointGSParams params = { 0 };
params.PointSize = pointSize;
params.TexOffset = texOffset;
D3D::context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0);
D3D::context->GSSetShader(shaderIt->second, NULL, 0);
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
return true;
}
else
return false;
}
else
return false;
}
}
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "PointGeometryShader.h"
#include <sstream>
#include "D3DBase.h"
#include "D3DShader.h"
#include "VertexShaderGen.h"
namespace DX11
{
union PointGSParams
{
struct
{
FLOAT PointSize; // In units of 1/6 of an EFB pixel
FLOAT TexOffset;
};
// Constant buffers must be a multiple of 16 bytes in size.
u8 pad[16]; // Pad to the next multiple of 16 bytes
};
static const char POINT_GS_COMMON[] =
// The struct VS_OUTPUT used by the vertex shader goes here.
"// dolphin-emu point geometry shader common part\n"
"cbuffer cbParams : register(b0)\n"
"{\n"
"struct\n" // Should match PointGSParams above
"{\n"
"float PointSize;\n"
"float TexOffset;\n"
"} Params;\n"
"}\n"
"[maxvertexcount(4)]\n"
"void main(point VS_OUTPUT input[1], inout TriangleStream<VS_OUTPUT> outStream)\n"
"{\n"
// Correct w coordinate so screen-space math will work
"VS_OUTPUT ptLL = input[0];\n"
"ptLL.pos /= ptLL.pos.w;\n"
"VS_OUTPUT ptLR = ptLL;\n"
"VS_OUTPUT ptUL = ptLL;\n"
"VS_OUTPUT ptUR = ptLL;\n"
// Distance from center to upper right vertex
"float2 offset = float2(Params.PointSize/640, -Params.PointSize/528);\n"
"ptLL.pos.xy += float2(-1,-1) * offset;\n"
"ptLR.pos.xy += float2(1,-1) * offset;\n"
"ptUL.pos.xy += float2(-1,1) * offset;\n"
"ptUR.pos.xy += offset;\n"
"float2 texOffset = float2(Params.TexOffset, Params.TexOffset);\n"
"#ifndef NUM_TEXCOORDS\n"
"#error NUM_TEXCOORDS not defined\n"
"#endif\n"
// Apply TexOffset to all tex coordinates in the vertex
"#if NUM_TEXCOORDS >= 1\n"
"ptLL.tex0.xy += float2(0,1) * texOffset;\n"
"ptLR.tex0.xy += texOffset;\n"
"ptUR.tex0.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 2\n"
"ptLL.tex1.xy += float2(0,1) * texOffset;\n"
"ptLR.tex1.xy += texOffset;\n"
"ptUR.tex1.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 3\n"
"ptLL.tex2.xy += float2(0,1) * texOffset;\n"
"ptLR.tex2.xy += texOffset;\n"
"ptUR.tex2.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 4\n"
"ptLL.tex3.xy += float2(0,1) * texOffset;\n"
"ptLR.tex3.xy += texOffset;\n"
"ptUR.tex3.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 5\n"
"ptLL.tex4.xy += float2(0,1) * texOffset;\n"
"ptLR.tex4.xy += texOffset;\n"
"ptUR.tex4.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 6\n"
"ptLL.tex5.xy += float2(0,1) * texOffset;\n"
"ptLR.tex5.xy += texOffset;\n"
"ptUR.tex5.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 7\n"
"ptLL.tex6.xy += float2(0,1) * texOffset;\n"
"ptLR.tex6.xy += texOffset;\n"
"ptUR.tex6.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"#if NUM_TEXCOORDS >= 8\n"
"ptLL.tex7.xy += float2(0,1) * texOffset;\n"
"ptLR.tex7.xy += texOffset;\n"
"ptUR.tex7.xy += float2(1,0) * texOffset;\n"
"#endif\n"
"outStream.Append(ptLL);\n"
"outStream.Append(ptLR);\n"
"outStream.Append(ptUL);\n"
"outStream.Append(ptUR);\n"
"}\n"
;
PointGeometryShader::PointGeometryShader()
: m_ready(false), m_paramsBuffer(NULL)
{ }
void PointGeometryShader::Init()
{
m_ready = false;
HRESULT hr;
// Create constant buffer for uploading data to geometry shader
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams),
D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_paramsBuffer);
CHECK(SUCCEEDED(hr), "create point geometry shader params buffer");
D3D::SetDebugObjectName(m_paramsBuffer, "point geometry shader params buffer");
m_ready = true;
}
void PointGeometryShader::Shutdown()
{
m_ready = false;
for (ComboMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_shaders.clear();
SAFE_RELEASE(m_paramsBuffer);
}
bool PointGeometryShader::SetShader(u32 components, float pointSize, float texOffset)
{
if (!m_ready)
return false;
// Make sure geometry shader for "components" is available
ComboMap::iterator shaderIt = m_shaders.find(components);
if (shaderIt == m_shaders.end())
{
// Generate new shader. Warning: not thread-safe.
static char code[16384];
char* p = code;
p = GenerateVSOutputStruct(p, components, API_D3D11);
p += sprintf(p, "\n%s", POINT_GS_COMMON);
std::stringstream numTexCoordsStr;
numTexCoordsStr << xfregs.numTexGen.numTexGens;
INFO_LOG(VIDEO, "Compiling point geometry shader for components 0x%.08X (num texcoords %d)",
components, xfregs.numTexGen.numTexGens);
D3D_SHADER_MACRO macros[] = {
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ NULL, NULL }
};
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
if (!newShader)
{
WARN_LOG(VIDEO, "Point geometry shader for components 0x%.08X failed to compile", components);
// Add dummy shader to prevent trying to compile again
m_shaders[components] = NULL;
return false;
}
shaderIt = m_shaders.insert(std::make_pair(components, newShader)).first;
}
if (shaderIt != m_shaders.end())
{
if (shaderIt->second)
{
PointGSParams params = { 0 };
params.PointSize = pointSize;
params.TexOffset = texOffset;
D3D::context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0);
D3D::context->GSSetShader(shaderIt->second, NULL, 0);
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
return true;
}
else
return false;
}
else
return false;
}
}

View File

@ -0,0 +1,114 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _POINTGEOMETRYSHADER_H
#define _POINTGEOMETRYSHADER_H
#include "VideoCommon.h"
struct ID3D11Buffer;
struct ID3D11GeometryShader;
namespace DX11
{
// This class manages a collection of point geometry shaders, one for each
// vertex format.
class PointGeometryShader
{
public:
PointGeometryShader();
void Init();
void Shutdown();
// Returns true on success, false on failure
bool SetShader(u32 components, float pointSize, float texOffset);
private:
bool m_ready;
ID3D11Buffer* m_paramsBuffer;
typedef std::map<u32, ID3D11GeometryShader*> ComboMap;
ComboMap m_shaders;
};
}
#endif
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _POINTGEOMETRYSHADER_H
#define _POINTGEOMETRYSHADER_H
#include "VideoCommon.h"
struct ID3D11Buffer;
struct ID3D11GeometryShader;
namespace DX11
{
// This class manages a collection of point geometry shaders, one for each
// vertex format.
class PointGeometryShader
{
public:
PointGeometryShader();
void Init();
void Shutdown();
// Returns true on success, false on failure
bool SetShader(u32 components, float pointSize, float texOffset);
private:
bool m_ready;
ID3D11Buffer* m_paramsBuffer;
typedef std::map<u32, ID3D11GeometryShader*> ComboMap;
ComboMap m_shaders;
};
}
#endif

View File

@ -64,10 +64,16 @@ void VertexManager::CreateDeviceObjects()
m_triangleDrawIndex = 0; m_triangleDrawIndex = 0;
m_lineDrawIndex = 0; m_lineDrawIndex = 0;
m_pointDrawIndex = 0; m_pointDrawIndex = 0;
m_lineShader.Init();
m_pointShader.Init();
} }
void VertexManager::DestroyDeviceObjects() void VertexManager::DestroyDeviceObjects()
{ {
m_pointShader.Shutdown();
m_lineShader.Shutdown();
SAFE_RELEASE(m_vertexBuffer); SAFE_RELEASE(m_vertexBuffer);
SAFE_RELEASE(m_indexBuffer); SAFE_RELEASE(m_indexBuffer);
} }
@ -126,6 +132,10 @@ void VertexManager::LoadBuffers()
m_indexBufferCursor += iCount; m_indexBufferCursor += iCount;
} }
static const float LINE_PT_TEX_OFFSETS[8] = {
0.f, 0.0625f, 0.125f, 0.25f, 0.5f, 1.f, 1.f, 1.f
};
void VertexManager::Draw(UINT stride) void VertexManager::Draw(UINT stride)
{ {
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset); D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset);
@ -138,16 +148,32 @@ void VertexManager::Draw(UINT stride)
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
if (IndexGenerator::GetNumLines() > 0) if (IndexGenerator::GetNumLines() > 0)
{
float lineWidth = float(bpmem.lineptwidth.linesize) / 6.f;
float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff];
if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth, texOffset))
{ {
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0); D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0);
}
} }
if (IndexGenerator::GetNumPoints() > 0) if (IndexGenerator::GetNumPoints() > 0)
{
float pointSize = float(bpmem.lineptwidth.pointsize) / 6.f;
float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff];
if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize, texOffset))
{ {
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0); D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0);
}
} }
} }

View File

@ -19,7 +19,8 @@
#define _VERTEXMANAGER_H #define _VERTEXMANAGER_H
#include "VertexManagerBase.h" #include "VertexManagerBase.h"
#include "LineGeometryShader.h"
#include "PointGeometryShader.h"
namespace DX11 namespace DX11
{ {
@ -48,6 +49,9 @@ private:
UINT m_pointDrawIndex; UINT m_pointDrawIndex;
ID3D11Buffer* m_indexBuffer; ID3D11Buffer* m_indexBuffer;
ID3D11Buffer* m_vertexBuffer; ID3D11Buffer* m_vertexBuffer;
LineGeometryShader m_lineShader;
PointGeometryShader m_pointShader;
}; };
} // namespace } // namespace