1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Renderer/BsRendererMaterialManager.h"
4#include "Renderer/BsRendererMaterial.h"
5#include "Resources/BsBuiltinResources.h"
6#include "CoreThread/BsCoreThread.h"
7#include "Material/BsShader.h"
8
9namespace bs
10{
11 RendererMaterialManager::RendererMaterialManager()
12 {
13 BuiltinResources& br = BuiltinResources::instance();
14
15 // Note: Ideally I want to avoid loading all materials, and instead just load those that are used.
16 Vector<RendererMaterialData>& materials = getMaterials();
17 Vector<SPtr<ct::Shader>> shaders;
18 for (auto& material : materials)
19 {
20 HShader shader = br.getShader(material.shaderPath);
21 if (shader.isLoaded())
22 shaders.push_back(shader->getCore());
23 else
24 shaders.push_back(nullptr);
25 }
26
27 gCoreThread().queueCommand(std::bind(&RendererMaterialManager::initOnCore, shaders), CTQF_InternalQueue);
28 }
29
30 RendererMaterialManager::~RendererMaterialManager()
31 {
32 gCoreThread().queueCommand(std::bind(&RendererMaterialManager::destroyOnCore));
33 }
34
35 void RendererMaterialManager::_registerMaterial(ct::RendererMaterialMetaData* metaData, const char* shaderPath)
36 {
37 Lock lock(getMutex());
38
39 Vector<RendererMaterialData>& materials = getMaterials();
40 materials.push_back({ metaData, shaderPath });
41 }
42
43 void RendererMaterialManager::initOnCore(const Vector<SPtr<ct::Shader>>& shaders)
44 {
45 Lock lock(getMutex());
46
47 Vector<RendererMaterialData>& materials = getMaterials();
48 for (UINT32 i = 0; i < materials.size(); i++)
49 {
50 materials[i].metaData->shaderPath = materials[i].shaderPath;
51 materials[i].metaData->shader = shaders[i];
52
53 // Note: Making the assumption here that all the techniques are generated due to shader variations
54 Vector<SPtr<ct::Technique>> techniques = shaders[i]->getCompatibleTechniques();
55 materials[i].metaData->instances.resize((UINT32)techniques.size());
56
57 for(auto& entry : techniques)
58 materials[i].metaData->variations.add(entry->getVariation());
59
60#if BS_PROFILING_ENABLED
61 const String& filename = materials[i].shaderPath.getFilename(false);
62 materials[i].metaData->profilerSampleName = ProfilerString("RM: ") +
63 ProfilerString(filename.data(), filename.size());
64#endif
65 }
66 }
67
68 ShaderDefines RendererMaterialManager::_getDefines(const Path& shaderPath)
69 {
70 ShaderDefines output;
71
72 Vector<RendererMaterialData>& materials = getMaterials();
73 for (auto& entry : materials)
74 {
75 if (entry.shaderPath == shaderPath)
76 return entry.metaData->defines;
77 }
78
79 return output;
80 }
81
82 void RendererMaterialManager::destroyOnCore()
83 {
84 Lock lock(getMutex());
85
86 Vector<RendererMaterialData>& materials = getMaterials();
87 for (UINT32 i = 0; i < materials.size(); i++)
88 {
89 materials[i].metaData->shader = nullptr;
90 materials[i].metaData->overrideShader = nullptr;
91
92 for (auto& entry : materials[i].metaData->instances)
93 {
94 if(entry != nullptr)
95 bs_delete(entry);
96 }
97
98 materials[i].metaData->instances.clear();
99 }
100 }
101
102 Vector<RendererMaterialManager::RendererMaterialData>& RendererMaterialManager::getMaterials()
103 {
104 static Vector<RendererMaterialData> materials;
105 return materials;
106 }
107
108 Mutex& RendererMaterialManager::getMutex()
109 {
110 static Mutex mutex;
111 return mutex;
112 }
113}
114