summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/D3DCommon/Shader.cpp
diff options
context:
space:
mode:
authorConnor McLaughlin <stenzek@gmail.com>2019-03-29 20:40:06 +1000
committerGitHub <noreply@github.com>2019-03-29 20:40:06 +1000
commitf3fadd730218429a5f6472283d16d30d7e276f8d (patch)
treed1d6577cd52b2d3b3d7872aef4fac80dbd0ce563 /Source/Core/VideoBackends/D3DCommon/Shader.cpp
parentfbe57e8dbef17e583f0ba0208af7bf414a3716bf (diff)
parentd0d010f8549cc902829f567b3b5127d9a0556ca5 (diff)
Merge pull request #7869 from stenzek/d3dcommon
D3D: Move sharable D3D11/D3D12 code to common library
Diffstat (limited to 'Source/Core/VideoBackends/D3DCommon/Shader.cpp')
-rw-r--r--Source/Core/VideoBackends/D3DCommon/Shader.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/D3DCommon/Shader.cpp b/Source/Core/VideoBackends/D3DCommon/Shader.cpp
new file mode 100644
index 0000000000..d53c5ab2e4
--- /dev/null
+++ b/Source/Core/VideoBackends/D3DCommon/Shader.cpp
@@ -0,0 +1,145 @@
+// Copyright 2019 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <fstream>
+#include <wrl/client.h>
+
+#include "Common/Assert.h"
+#include "Common/FileUtil.h"
+#include "Common/Logging/Log.h"
+#include "Common/MsgHandler.h"
+#include "Common/StringUtil.h"
+
+#include "VideoBackends/D3DCommon/Shader.h"
+#include "VideoCommon/VideoConfig.h"
+
+namespace D3DCommon
+{
+Shader::Shader(ShaderStage stage, BinaryData bytecode)
+ : AbstractShader(stage), m_bytecode(std::move(bytecode))
+{
+}
+
+Shader::~Shader() = default;
+
+bool Shader::HasBinary() const
+{
+ return true;
+}
+
+AbstractShader::BinaryData Shader::GetBinary() const
+{
+ return m_bytecode;
+}
+
+static const char* GetCompileTarget(D3D_FEATURE_LEVEL feature_level, ShaderStage stage)
+{
+ switch (stage)
+ {
+ case ShaderStage::Vertex:
+ {
+ switch (feature_level)
+ {
+ case D3D_FEATURE_LEVEL_10_0:
+ return "vs_4_0";
+ case D3D_FEATURE_LEVEL_10_1:
+ return "vs_4_1";
+ default:
+ return "vs_5_0";
+ }
+ }
+
+ case ShaderStage::Geometry:
+ {
+ switch (feature_level)
+ {
+ case D3D_FEATURE_LEVEL_10_0:
+ return "gs_4_0";
+ case D3D_FEATURE_LEVEL_10_1:
+ return "gs_4_1";
+ default:
+ return "gs_5_0";
+ }
+ }
+
+ case ShaderStage::Pixel:
+ {
+ switch (feature_level)
+ {
+ case D3D_FEATURE_LEVEL_10_0:
+ return "ps_4_0";
+ case D3D_FEATURE_LEVEL_10_1:
+ return "ps_4_1";
+ default:
+ return "ps_5_0";
+ }
+ }
+
+ case ShaderStage::Compute:
+ {
+ switch (feature_level)
+ {
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ return "";
+
+ default:
+ return "cs_5_0";
+ }
+ }
+
+ default:
+ return "";
+ }
+}
+
+bool Shader::CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_bytecode,
+ ShaderStage stage, const char* source, size_t length)
+{
+ static constexpr D3D_SHADER_MACRO macros[] = {{"API_D3D", "1"}, {nullptr, nullptr}};
+ const UINT flags = g_ActiveConfig.bEnableValidationLayer ?
+ (D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION) :
+ (D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_SKIP_VALIDATION);
+ const char* target = GetCompileTarget(feature_level, stage);
+
+ Microsoft::WRL::ComPtr<ID3DBlob> code;
+ Microsoft::WRL::ComPtr<ID3DBlob> errors;
+ HRESULT hr = d3d_compile(source, length, nullptr, macros, nullptr, "main", target, flags, 0,
+ &code, &errors);
+ if (FAILED(hr))
+ {
+ static int num_failures = 0;
+ std::string filename = StringFromFormat(
+ "%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), target, num_failures++);
+ std::ofstream file;
+ File::OpenFStream(file, filename, std::ios_base::out);
+ file.write(source, length);
+ file << "\n";
+ file.write(static_cast<const char*>(errors->GetBufferPointer()), errors->GetBufferSize());
+ file.close();
+
+ PanicAlert("Failed to compile %s:\nDebug info (%s):\n%s", filename.c_str(), target,
+ static_cast<const char*>(errors->GetBufferPointer()));
+ return false;
+ }
+
+ if (errors && errors->GetBufferSize() > 0)
+ {
+ WARN_LOG(VIDEO, "%s compilation succeeded with warnings:\n%s", target,
+ static_cast<const char*>(errors->GetBufferPointer()));
+ }
+
+ out_bytecode->resize(code->GetBufferSize());
+ std::memcpy(out_bytecode->data(), code->GetBufferPointer(), code->GetBufferSize());
+ return true;
+}
+
+AbstractShader::BinaryData Shader::CreateByteCode(const void* data, size_t length)
+{
+ BinaryData bytecode(length);
+ std::memcpy(bytecode.data(), data, length);
+ return bytecode;
+}
+
+} // namespace D3DCommon