#include "EffekseerMaterialCompilerDX9.h" #include "../HLSLGenerator/ShaderGenerator.h" #include #include #include #include #pragma comment(lib, "d3dcompiler.lib") namespace Effekseer { namespace DX9 { 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_3_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_3_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 DX9 } // namespace Effekseer namespace Effekseer { const int32_t DX9_ModelRendererInstanceCount = 10; class CompiledMaterialBinaryDX9 : public CompiledMaterialBinary, public ReferenceObject { private: std::array, static_cast(MaterialShaderType::Max)> vertexShaders_; std::array, static_cast(MaterialShaderType::Max)> pixelShaders_; public: CompiledMaterialBinaryDX9() { } virtual ~CompiledMaterialBinaryDX9() { } 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* MaterialCompilerDX9::Compile(MaterialFile* materialFile, int32_t maximumUniformCount, int32_t maximumTextureCount) { auto binary = new CompiledMaterialBinaryDX9(); auto convertToVectorVS = [](const std::string& str) -> std::vector { std::vector ret; std::string log; std::vector macros; auto blob = DX9::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 = DX9::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) { auto generator = DirectX::ShaderGenerator(DirectX::ShaderGeneratorTarget::DirectX9); auto shader = generator.GenerateShader(materialFile, type, maximumUniformCount, maximumTextureCount, 0, DX9_ModelRendererInstanceCount); binary->SetVertexShaderData(type, convertToVectorVS(shader.CodeVS)); binary->SetPixelShaderData(type, convertToVectorPS(shader.CodePS)); }; if (materialFile->GetHasRefraction()) { saveBinary(MaterialShaderType::Refraction); saveBinary(MaterialShaderType::RefractionModel); } saveBinary(MaterialShaderType::Standard); saveBinary(MaterialShaderType::Model); return binary; } CompiledMaterialBinary* MaterialCompilerDX9::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::MaterialCompilerDX9(); } } #endif