#include "EffekseerMaterialCompilerDX11.h" #include "../HLSLGenerator/ShaderGenerator.h" #include #include #include #pragma comment(lib, "d3dcompiler.lib") namespace Effekseer { namespace DX11 { static ID3DBlob* CompileVertexShader(const char* vertexShaderText, const char* vertexShaderFileName, const std::vector& macro, std::string& log) { ID3DBlob* shader = nullptr; ID3DBlob* error = nullptr; UINT flag = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR; #if !_DEBUG flag = flag | D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif HRESULT hr; hr = D3DCompile(vertexShaderText, strlen(vertexShaderText), vertexShaderFileName, macro.size() > 0 ? (D3D_SHADER_MACRO*)¯o[0] : nullptr, nullptr, "main", "vs_4_0", flag, 0, &shader, &error); if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) { log += "Out of memory\n"; } else { log += "Unknown error\n"; } if (error != nullptr) { log += (const char*)error->GetBufferPointer(); error->Release(); } ES_SAFE_RELEASE(shader); return nullptr; } return shader; } static ID3DBlob* CompilePixelShader(const char* vertexShaderText, const char* vertexShaderFileName, const std::vector& macro, std::string& log) { ID3DBlob* shader = nullptr; ID3DBlob* error = nullptr; UINT flag = D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR; #if !_DEBUG flag = flag | D3D10_SHADER_OPTIMIZATION_LEVEL3; #endif HRESULT hr; hr = D3DCompile(vertexShaderText, strlen(vertexShaderText), vertexShaderFileName, macro.size() > 0 ? (D3D_SHADER_MACRO*)¯o[0] : nullptr, nullptr, "main", "ps_4_0", flag, 0, &shader, &error); if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) { log += "Out of memory\n"; } else { log += "Unknown error\n"; } if (error != nullptr) { log += (const char*)error->GetBufferPointer(); error->Release(); } ES_SAFE_RELEASE(shader); return nullptr; } return shader; } } // namespace DX11 } // namespace Effekseer namespace Effekseer { class CompiledMaterialBinaryDX11 : public CompiledMaterialBinary, public ReferenceObject { private: std::array, static_cast(MaterialShaderType::Max)> vertexShaders_; std::array, static_cast(MaterialShaderType::Max)> pixelShaders_; public: CompiledMaterialBinaryDX11() { } virtual ~CompiledMaterialBinaryDX11() { } void SetVertexShaderData(MaterialShaderType type, const std::vector& data) { vertexShaders_.at(static_cast(type)) = data; } void SetPixelShaderData(MaterialShaderType type, const std::vector& data) { pixelShaders_.at(static_cast(type)) = data; } const uint8_t* GetVertexShaderData(MaterialShaderType type) const override { return vertexShaders_.at(static_cast(type)).data(); } int32_t GetVertexShaderSize(MaterialShaderType type) const override { return static_cast(vertexShaders_.at(static_cast(type)).size()); } const uint8_t* GetPixelShaderData(MaterialShaderType type) const override { return pixelShaders_.at(static_cast(type)).data(); } int32_t GetPixelShaderSize(MaterialShaderType type) const override { return static_cast(pixelShaders_.at(static_cast(type)).size()); } int AddRef() override { return ReferenceObject::AddRef(); } int Release() override { return ReferenceObject::Release(); } int GetRef() override { return ReferenceObject::GetRef(); } }; CompiledMaterialBinary* MaterialCompilerDX11::Compile(MaterialFile* materialFile, int32_t maximumUniformCount, int32_t maximumTextureCount) { auto binary = new CompiledMaterialBinaryDX11(); auto convertToVectorVS = [](const std::string& str) -> std::vector { std::vector ret; std::string log; std::vector macros; auto blob = DX11::CompileVertexShader(str.c_str(), "VS", macros, log); if (blob != nullptr) { ret.resize(blob->GetBufferSize()); memcpy(ret.data(), blob->GetBufferPointer(), ret.size()); blob->Release(); } else { std::cout << "VertexShader Compile Error" << std::endl; std::cout << log << std::endl; std::cout << str << std::endl; } return ret; }; auto convertToVectorPS = [](const std::string& str) -> std::vector { std::vector ret; std::string log; std::vector macros; auto blob = DX11::CompilePixelShader(str.c_str(), "PS", macros, log); if (blob != nullptr) { ret.resize(blob->GetBufferSize()); memcpy(ret.data(), blob->GetBufferPointer(), ret.size()); blob->Release(); } else { std::cout << "PixelShader Compile Error" << std::endl; std::cout << log << std::endl; std::cout << str << std::endl; } return ret; }; auto saveBinary = [&materialFile, &binary, &convertToVectorVS, &convertToVectorPS, &maximumUniformCount, &maximumTextureCount](MaterialShaderType type) -> bool { auto generator = DirectX::ShaderGenerator(DirectX::ShaderGeneratorTarget::DirectX11); auto shader = generator.GenerateShader(materialFile, type, maximumUniformCount, maximumTextureCount, 0, 40); auto vsBuffer = convertToVectorVS(shader.CodeVS); auto psBuffer = convertToVectorPS(shader.CodePS); if (vsBuffer.size() == 0 || psBuffer.size() == 0) { return false; } binary->SetVertexShaderData(type, vsBuffer); binary->SetPixelShaderData(type, psBuffer); return true; }; if (materialFile->GetHasRefraction()) { if (!saveBinary(MaterialShaderType::Refraction) || !saveBinary(MaterialShaderType::RefractionModel)) { return nullptr; } } if (!saveBinary(MaterialShaderType::Standard) || !saveBinary(MaterialShaderType::Model)) { return nullptr; } return binary; } CompiledMaterialBinary* MaterialCompilerDX11::Compile(MaterialFile* materialFile) { return Compile(materialFile, Effekseer::UserUniformSlotMax, Effekseer::UserTextureSlotMax); } } // namespace Effekseer #ifdef __SHARED_OBJECT__ extern "C" { #ifdef _WIN32 #define EFK_EXPORT __declspec(dllexport) #else #define EFK_EXPORT #endif EFK_EXPORT Effekseer::MaterialCompiler* EFK_STDCALL CreateCompiler() { return new Effekseer::MaterialCompilerDX11(); } } #endif