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:
parent
8fedc3db38
commit
7c536b8f15
|
@ -73,6 +73,37 @@ static char text[16384];
|
|||
|
||||
#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)
|
||||
{
|
||||
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"
|
||||
);
|
||||
|
||||
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");
|
||||
p = GenerateVSOutputStruct(p, components, api_type);
|
||||
|
||||
// uniforms
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ public:
|
|||
|
||||
|
||||
// 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);
|
||||
void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components);
|
||||
|
||||
|
|
|
@ -197,9 +197,11 @@
|
|||
<ClCompile Include="Src\D3DUtil.cpp" />
|
||||
<ClCompile Include="Src\FramebufferManager.cpp" />
|
||||
<ClCompile Include="Src\GfxState.cpp" />
|
||||
<ClCompile Include="Src\LineGeometryShader.cpp" />
|
||||
<ClCompile Include="Src\main.cpp" />
|
||||
<ClCompile Include="Src\NativeVertexFormat.cpp" />
|
||||
<ClCompile Include="Src\PixelShaderCache.cpp" />
|
||||
<ClCompile Include="Src\PointGeometryShader.cpp" />
|
||||
<ClCompile Include="Src\PSTextureEncoder.cpp" />
|
||||
<ClCompile Include="Src\Render.cpp" />
|
||||
<ClCompile Include="Src\stdafx.cpp">
|
||||
|
@ -225,8 +227,10 @@
|
|||
<ClInclude Include="Src\FramebufferManager.h" />
|
||||
<ClInclude Include="Src\GfxState.h" />
|
||||
<ClInclude Include="Src\Globals.h" />
|
||||
<ClInclude Include="Src\LineGeometryShader.h" />
|
||||
<ClInclude Include="Src\main.h" />
|
||||
<ClInclude Include="Src\PixelShaderCache.h" />
|
||||
<ClInclude Include="Src\PointGeometryShader.h" />
|
||||
<ClInclude Include="Src\PSTextureEncoder.h" />
|
||||
<ClInclude Include="Src\Render.h" />
|
||||
<ClInclude Include="Src\stdafx.h" />
|
||||
|
|
|
@ -51,6 +51,12 @@
|
|||
<ClCompile Include="Src\Television.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\LineGeometryShader.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\PointGeometryShader.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\Globals.h" />
|
||||
|
@ -105,6 +111,12 @@
|
|||
<ClInclude Include="Src\Television.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\LineGeometryShader.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PointGeometryShader.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="D3D">
|
||||
|
|
|
@ -415,7 +415,6 @@ void Close()
|
|||
UnloadDXGI();
|
||||
}
|
||||
|
||||
/* just returning the 4_0 ones here */
|
||||
const char* VertexShaderVersionString()
|
||||
{
|
||||
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";
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if(featlevel == D3D_FEATURE_LEVEL_11_0) return "ps_5_0";
|
||||
|
|
|
@ -64,6 +64,7 @@ unsigned int GetBackBufferWidth();
|
|||
unsigned int GetBackBufferHeight();
|
||||
D3DTexture2D* &GetBackBuffer();
|
||||
const char* PixelShaderVersionString();
|
||||
const char* GeometryShaderVersionString();
|
||||
const char* VertexShaderVersionString();
|
||||
bool BGRATexturesSupported();
|
||||
|
||||
|
|
|
@ -82,6 +82,61 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
|
|||
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
|
||||
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);
|
||||
}
|
||||
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len)
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code,
|
||||
unsigned int len)
|
||||
{
|
||||
D3DBlob* blob = NULL;
|
||||
if (CompileVertexShader(code, len, &blob))
|
||||
|
@ -151,7 +207,22 @@ ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int
|
|||
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;
|
||||
CompilePixelShader(code, len, &blob);
|
||||
|
|
|
@ -29,20 +29,38 @@ namespace DX11
|
|||
namespace D3D
|
||||
{
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len);
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len);
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len);
|
||||
|
||||
// The returned bytecode buffers should be Release()d.
|
||||
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob);
|
||||
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = NULL);
|
||||
bool CompileVertexShader(const char* code, unsigned int len,
|
||||
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
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len);
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len);
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code,
|
||||
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 ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
|
||||
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code) { return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); }
|
||||
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code) { return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); }
|
||||
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode)
|
||||
{ return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); }
|
||||
inline ID3D11GeometryShader* CreateGeometryShaderFromByteCode(D3DBlob* bytecode)
|
||||
{ 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
|
|
@ -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, ¶ms, 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, ¶ms, 0, 0);
|
||||
|
||||
D3D::context->GSSetShader(shaderIt->second, NULL, 0);
|
||||
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -1265,10 +1265,8 @@ bool PSTextureEncoder::SetStaticShader(unsigned int dstFormat, unsigned int srcF
|
|||
HRESULT hr = D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), NULL, &newShader);
|
||||
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
|
||||
|
||||
m_staticShaders[key] = newShader;
|
||||
it = m_staticShaders.insert(std::make_pair(key, newShader)).first;
|
||||
bytecode->Release();
|
||||
|
||||
it = m_staticShaders.find(key);
|
||||
}
|
||||
|
||||
if (it != m_staticShaders.end())
|
||||
|
|
|
@ -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, ¶ms, 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, ¶ms, 0, 0);
|
||||
|
||||
D3D::context->GSSetShader(shaderIt->second, NULL, 0);
|
||||
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -64,10 +64,16 @@ void VertexManager::CreateDeviceObjects()
|
|||
m_triangleDrawIndex = 0;
|
||||
m_lineDrawIndex = 0;
|
||||
m_pointDrawIndex = 0;
|
||||
|
||||
m_lineShader.Init();
|
||||
m_pointShader.Init();
|
||||
}
|
||||
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
m_pointShader.Shutdown();
|
||||
m_lineShader.Shutdown();
|
||||
|
||||
SAFE_RELEASE(m_vertexBuffer);
|
||||
SAFE_RELEASE(m_indexBuffer);
|
||||
}
|
||||
|
@ -126,6 +132,10 @@ void VertexManager::LoadBuffers()
|
|||
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)
|
||||
{
|
||||
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset);
|
||||
|
@ -139,15 +149,31 @@ void VertexManager::Draw(UINT stride)
|
|||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
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->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
|
||||
D3D::context->GSSetShader(NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
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->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
|
||||
D3D::context->GSSetShader(NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#define _VERTEXMANAGER_H
|
||||
|
||||
#include "VertexManagerBase.h"
|
||||
|
||||
#include "LineGeometryShader.h"
|
||||
#include "PointGeometryShader.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
@ -48,6 +49,9 @@ private:
|
|||
UINT m_pointDrawIndex;
|
||||
ID3D11Buffer* m_indexBuffer;
|
||||
ID3D11Buffer* m_vertexBuffer;
|
||||
|
||||
LineGeometryShader m_lineShader;
|
||||
PointGeometryShader m_pointShader;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue