diff options
| author | Connor McLaughlin <stenzek@gmail.com> | 2019-03-29 20:40:06 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-03-29 20:40:06 +1000 |
| commit | f3fadd730218429a5f6472283d16d30d7e276f8d (patch) | |
| tree | d1d6577cd52b2d3b3d7872aef4fac80dbd0ce563 /Source/Core/VideoBackends/D3DCommon/Shader.cpp | |
| parent | fbe57e8dbef17e583f0ba0208af7bf414a3716bf (diff) | |
| parent | d0d010f8549cc902829f567b3b5127d9a0556ca5 (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.cpp | 145 |
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 |
