2015-05-23 22:55:12 -06:00
|
|
|
// Copyright 2010 Dolphin Emulator Project
|
2015-05-17 17:08:10 -06:00
|
|
|
// Licensed under GPLv2+
|
2013-04-17 21:29:41 -06:00
|
|
|
// Refer to the license.txt file included.
|
2010-06-13 13:50:06 -06:00
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
2014-06-02 23:08:54 -06:00
|
|
|
#include "Common/StringUtil.h"
|
2014-02-17 03:18:15 -07:00
|
|
|
#include "VideoBackends/D3D/D3DBase.h"
|
|
|
|
#include "VideoBackends/D3D/D3DShader.h"
|
|
|
|
#include "VideoCommon/VideoConfig.h"
|
2010-06-13 13:50:06 -06:00
|
|
|
|
2011-01-29 13:16:51 -07:00
|
|
|
namespace DX11
|
|
|
|
{
|
|
|
|
|
2010-06-13 13:50:06 -06:00
|
|
|
namespace D3D
|
|
|
|
{
|
|
|
|
|
|
|
|
// bytecode->shader
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len)
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11VertexShader* v_shader;
|
2014-03-09 14:14:26 -06:00
|
|
|
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, nullptr, &v_shader);
|
2010-06-13 13:50:06 -06:00
|
|
|
if (FAILED(hr))
|
2014-03-09 14:14:26 -06:00
|
|
|
return nullptr;
|
2011-07-29 16:18:11 -06:00
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
return v_shader;
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
// code->bytecode
|
2014-07-07 17:28:12 -06:00
|
|
|
bool CompileVertexShader(const std::string& code, D3DBlob** blob)
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2014-03-09 14:14:26 -06:00
|
|
|
ID3D10Blob* shaderBuffer = nullptr;
|
|
|
|
ID3D10Blob* errorBuffer = nullptr;
|
2011-06-11 13:37:21 -06:00
|
|
|
|
|
|
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
2014-05-10 23:12:20 -06:00
|
|
|
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG;
|
2011-06-11 13:37:21 -06:00
|
|
|
#else
|
|
|
|
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
|
|
|
|
#endif
|
2014-07-07 17:28:12 -06:00
|
|
|
HRESULT hr = PD3DCompile(code.c_str(), code.length(), nullptr, nullptr, nullptr, "main", D3D::VertexShaderVersionString(),
|
2013-10-19 03:27:57 -06:00
|
|
|
flags, 0, &shaderBuffer, &errorBuffer);
|
2011-06-11 13:37:21 -06:00
|
|
|
if (errorBuffer)
|
|
|
|
{
|
|
|
|
INFO_LOG(VIDEO, "Vertex shader compiler messages:\n%s\n",
|
|
|
|
(const char*)errorBuffer->GetBufferPointer());
|
|
|
|
}
|
2011-03-30 01:17:23 -06:00
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
2011-07-29 16:18:11 -06:00
|
|
|
static int num_failures = 0;
|
2014-06-02 23:08:54 -06:00
|
|
|
std::string filename = StringFromFormat("%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
2013-02-28 18:33:39 -07:00
|
|
|
std::ofstream file;
|
2014-06-02 23:08:54 -06:00
|
|
|
OpenFStream(file, filename, std::ios_base::out);
|
2011-07-29 16:18:11 -06:00
|
|
|
file << code;
|
|
|
|
file.close();
|
|
|
|
|
2015-03-15 09:42:22 -06:00
|
|
|
PanicAlert("Failed to compile vertex shader: %s\nDebug info (%s):\n%s",
|
|
|
|
filename.c_str(), D3D::VertexShaderVersionString(), (const char*)errorBuffer->GetBufferPointer());
|
2011-06-11 13:37:21 -06:00
|
|
|
|
2014-03-09 14:14:26 -06:00
|
|
|
*blob = nullptr;
|
2011-06-11 13:37:21 -06:00
|
|
|
errorBuffer->Release();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*blob = new D3DBlob(shaderBuffer);
|
|
|
|
shaderBuffer->Release();
|
|
|
|
}
|
|
|
|
return SUCCEEDED(hr);
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
|
|
|
|
2011-03-14 03:38:29 -06:00
|
|
|
// bytecode->shader
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len)
|
2011-03-14 03:38:29 -06:00
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11GeometryShader* g_shader;
|
2014-03-09 14:14:26 -06:00
|
|
|
HRESULT hr = D3D::device->CreateGeometryShader(bytecode, len, nullptr, &g_shader);
|
2011-03-14 03:38:29 -06:00
|
|
|
if (FAILED(hr))
|
2014-03-09 14:14:26 -06:00
|
|
|
return nullptr;
|
2011-07-29 16:18:11 -06:00
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
return g_shader;
|
2011-03-14 03:38:29 -06:00
|
|
|
}
|
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
// code->bytecode
|
2014-07-07 17:28:12 -06:00
|
|
|
bool CompileGeometryShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines)
|
2011-03-14 03:38:29 -06:00
|
|
|
{
|
2014-03-09 14:14:26 -06:00
|
|
|
ID3D10Blob* shaderBuffer = nullptr;
|
|
|
|
ID3D10Blob* errorBuffer = nullptr;
|
2011-03-14 03:38:29 -06:00
|
|
|
|
|
|
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
2014-05-10 23:12:20 -06:00
|
|
|
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG;
|
2011-03-14 03:38:29 -06:00
|
|
|
#else
|
2011-06-11 13:37:21 -06:00
|
|
|
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
|
2011-03-14 03:38:29 -06:00
|
|
|
#endif
|
2014-07-07 17:28:12 -06:00
|
|
|
HRESULT hr = PD3DCompile(code.c_str(), code.length(), nullptr, pDefines, nullptr, "main", D3D::GeometryShaderVersionString(),
|
2013-10-19 03:27:57 -06:00
|
|
|
flags, 0, &shaderBuffer, &errorBuffer);
|
|
|
|
|
2011-03-30 01:17:23 -06:00
|
|
|
if (errorBuffer)
|
2011-03-14 03:38:29 -06:00
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
INFO_LOG(VIDEO, "Geometry shader compiler messages:\n%s\n",
|
2011-03-30 01:17:23 -06:00
|
|
|
(const char*)errorBuffer->GetBufferPointer());
|
2011-06-11 13:37:21 -06:00
|
|
|
}
|
2011-03-30 01:17:23 -06:00
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
2011-07-29 16:18:11 -06:00
|
|
|
static int num_failures = 0;
|
2014-06-02 23:08:54 -06:00
|
|
|
std::string filename = StringFromFormat("%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
2013-02-28 18:33:39 -07:00
|
|
|
std::ofstream file;
|
2014-06-02 23:08:54 -06:00
|
|
|
OpenFStream(file, filename, std::ios_base::out);
|
2011-07-29 16:18:11 -06:00
|
|
|
file << code;
|
|
|
|
file.close();
|
|
|
|
|
2015-03-15 09:42:22 -06:00
|
|
|
PanicAlert("Failed to compile geometry shader: %s\nDebug info (%s):\n%s",
|
|
|
|
filename.c_str(), D3D::GeometryShaderVersionString(), (const char*)errorBuffer->GetBufferPointer());
|
2011-06-11 13:37:21 -06:00
|
|
|
|
2014-03-09 14:14:26 -06:00
|
|
|
*blob = nullptr;
|
2011-03-14 03:38:29 -06:00
|
|
|
errorBuffer->Release();
|
|
|
|
}
|
2011-06-11 13:37:21 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*blob = new D3DBlob(shaderBuffer);
|
|
|
|
shaderBuffer->Release();
|
|
|
|
}
|
|
|
|
return SUCCEEDED(hr);
|
2011-03-14 03:38:29 -06:00
|
|
|
}
|
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
// bytecode->shader
|
|
|
|
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len)
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11PixelShader* p_shader;
|
2014-03-09 14:14:26 -06:00
|
|
|
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, nullptr, &p_shader);
|
2011-06-11 13:37:21 -06:00
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
|
2014-03-09 14:14:26 -06:00
|
|
|
p_shader = nullptr;
|
2011-06-11 13:37:21 -06:00
|
|
|
}
|
|
|
|
return p_shader;
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// code->bytecode
|
2014-07-07 17:28:12 -06:00
|
|
|
bool CompilePixelShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines)
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2014-03-09 14:14:26 -06:00
|
|
|
ID3D10Blob* shaderBuffer = nullptr;
|
|
|
|
ID3D10Blob* errorBuffer = nullptr;
|
2010-06-13 13:50:06 -06:00
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
2014-05-10 23:12:20 -06:00
|
|
|
UINT flags = D3D10_SHADER_DEBUG;
|
2011-06-11 13:37:21 -06:00
|
|
|
#else
|
|
|
|
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
|
|
|
|
#endif
|
2014-07-07 17:28:12 -06:00
|
|
|
HRESULT hr = PD3DCompile(code.c_str(), code.length(), nullptr, pDefines, nullptr, "main", D3D::PixelShaderVersionString(),
|
2013-10-19 03:27:57 -06:00
|
|
|
flags, 0, &shaderBuffer, &errorBuffer);
|
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
if (errorBuffer)
|
|
|
|
{
|
|
|
|
INFO_LOG(VIDEO, "Pixel shader compiler messages:\n%s",
|
|
|
|
(const char*)errorBuffer->GetBufferPointer());
|
|
|
|
}
|
2010-06-13 13:50:06 -06:00
|
|
|
|
2011-06-11 13:37:21 -06:00
|
|
|
if (FAILED(hr))
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2011-07-29 16:18:11 -06:00
|
|
|
static int num_failures = 0;
|
2014-06-02 23:08:54 -06:00
|
|
|
std::string filename = StringFromFormat("%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
2013-02-28 18:33:39 -07:00
|
|
|
std::ofstream file;
|
2014-06-02 23:08:54 -06:00
|
|
|
OpenFStream(file, filename, std::ios_base::out);
|
2011-07-29 16:18:11 -06:00
|
|
|
file << code;
|
|
|
|
file.close();
|
|
|
|
|
2015-03-15 09:42:22 -06:00
|
|
|
PanicAlert("Failed to compile pixel shader: %s\nDebug info (%s):\n%s",
|
|
|
|
filename.c_str(), D3D::PixelShaderVersionString(), (const char*)errorBuffer->GetBufferPointer());
|
2011-06-11 13:37:21 -06:00
|
|
|
|
2014-03-09 14:14:26 -06:00
|
|
|
*blob = nullptr;
|
2011-06-11 13:37:21 -06:00
|
|
|
errorBuffer->Release();
|
2010-06-16 17:25:19 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
*blob = new D3DBlob(shaderBuffer);
|
|
|
|
shaderBuffer->Release();
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
2011-06-11 13:37:21 -06:00
|
|
|
|
|
|
|
return SUCCEEDED(hr);
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
|
|
|
|
2014-07-07 17:28:12 -06:00
|
|
|
ID3D11VertexShader* CompileAndCreateVertexShader(const std::string& code)
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2014-03-09 14:14:26 -06:00
|
|
|
D3DBlob* blob = nullptr;
|
2014-07-07 17:28:12 -06:00
|
|
|
if (CompileVertexShader(code, &blob))
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
|
|
|
|
blob->Release();
|
|
|
|
return v_shader;
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
2014-03-09 14:14:26 -06:00
|
|
|
return nullptr;
|
2011-06-11 13:37:21 -06:00
|
|
|
}
|
|
|
|
|
2014-07-07 17:28:12 -06:00
|
|
|
ID3D11GeometryShader* CompileAndCreateGeometryShader(const std::string& code, const D3D_SHADER_MACRO* pDefines)
|
2011-06-11 13:37:21 -06:00
|
|
|
{
|
2014-03-09 14:14:26 -06:00
|
|
|
D3DBlob* blob = nullptr;
|
2014-07-07 17:28:12 -06:00
|
|
|
if (CompileGeometryShader(code, &blob, pDefines))
|
2011-03-14 03:38:29 -06:00
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11GeometryShader* g_shader = CreateGeometryShaderFromByteCode(blob);
|
|
|
|
blob->Release();
|
|
|
|
return g_shader;
|
2011-03-14 03:38:29 -06:00
|
|
|
}
|
2014-03-09 14:14:26 -06:00
|
|
|
return nullptr;
|
2011-03-14 03:38:29 -06:00
|
|
|
}
|
|
|
|
|
2014-07-07 17:28:12 -06:00
|
|
|
ID3D11PixelShader* CompileAndCreatePixelShader(const std::string& code)
|
2010-06-13 13:50:06 -06:00
|
|
|
{
|
2014-03-09 14:14:26 -06:00
|
|
|
D3DBlob* blob = nullptr;
|
2014-07-07 17:28:12 -06:00
|
|
|
CompilePixelShader(code, &blob);
|
2010-06-13 13:50:06 -06:00
|
|
|
if (blob)
|
|
|
|
{
|
2011-06-11 13:37:21 -06:00
|
|
|
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob);
|
|
|
|
blob->Release();
|
|
|
|
return p_shader;
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
2014-03-09 14:14:26 -06:00
|
|
|
return nullptr;
|
2010-06-13 13:50:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
2011-01-29 13:16:51 -07:00
|
|
|
|
2013-10-28 23:23:17 -06:00
|
|
|
} // namespace DX11
|