PixelShader.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Log.h"
  25. #include "PixelShader.h"
  26. #include "Profiler.h"
  27. #include "Renderer.h"
  28. #include "RendererImpl.h"
  29. #include "ResourceCache.h"
  30. #include "SharedArrayPtr.h"
  31. #include "StringUtils.h"
  32. #include "XMLFile.h"
  33. #include <ctype.h>
  34. #include "DebugNew.h"
  35. std::map<std::string, PSParameter> PixelShader::sParameters;
  36. std::map<std::string, TextureUnit> PixelShader::sTextureUnits;
  37. unsigned PixelShader::sRegisters[MAX_PS_PARAMETERS];
  38. const void* PixelShader::sLastParameterSources[MAX_PS_PARAMETERS];
  39. bool PixelShader::sInitialized = false;
  40. PixelShader::PixelShader(Renderer* renderer, const std::string& name) :
  41. Resource(name),
  42. GPUObject(renderer),
  43. mHash(0),
  44. mIsSM3(false)
  45. {
  46. for (unsigned i = 0; i < MAX_PS_PARAMETERS; ++i)
  47. mUseParameter[i] = false;
  48. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  49. mUseTextureUnit[i] = false;
  50. }
  51. PixelShader::~PixelShader()
  52. {
  53. release();
  54. }
  55. void PixelShader::load(Deserializer& source, ResourceCache* cache)
  56. {
  57. PROFILE(PixelShader_Load);
  58. release();
  59. if (!mRenderer)
  60. return;
  61. unsigned dataSize = source.getSize();
  62. setMemoryUse(dataSize);
  63. SharedArrayPtr<unsigned char> buffer(new unsigned char[dataSize]);
  64. source.read((void*)buffer.getPtr(), dataSize);
  65. if (FAILED(mRenderer->getImpl()->getDevice()->CreatePixelShader(
  66. (const DWORD*)buffer.getPtr(),
  67. (IDirect3DPixelShader9**)&mObject)))
  68. EXCEPTION("Could not create pixel shader " + getName());
  69. loadParameters(cache);
  70. mHash = *((unsigned short*)this) >> 2;
  71. }
  72. void PixelShader::release()
  73. {
  74. if (mObject)
  75. {
  76. if (!mRenderer)
  77. {
  78. LOGWARNING("Renderer has expired, skipping release of PixelShader");
  79. return;
  80. }
  81. if (mRenderer->getPixelShader() == this)
  82. mRenderer->setPixelShader(0);
  83. ((IDirect3DPixelShader9*)mObject)->Release();
  84. mObject = 0;
  85. }
  86. }
  87. PSParameter PixelShader::getParameter(const std::string& name)
  88. {
  89. initializeParameters();
  90. std::map<std::string, PSParameter>::iterator i = sParameters.find(name);
  91. if (i == sParameters.end())
  92. return MAX_PS_PARAMETERS;
  93. return i->second;
  94. }
  95. const std::string& PixelShader::getParameterName(PSParameter parameter)
  96. {
  97. static const std::string noParameter;
  98. initializeParameters();
  99. for (std::map<std::string, PSParameter>::iterator i = sParameters.begin(); i != sParameters.end(); ++i)
  100. {
  101. if (i->second == parameter)
  102. return i->first;
  103. }
  104. return noParameter;
  105. }
  106. void PixelShader::clearLastParameterSources()
  107. {
  108. for (unsigned i = 0; i < MAX_PS_PARAMETERS; ++i)
  109. sLastParameterSources[i] = (const void*)M_MAX_UNSIGNED;
  110. }
  111. void PixelShader::loadParameters(ResourceCache* cache)
  112. {
  113. if (!cache)
  114. return;
  115. initializeParameters();
  116. std::string shaderPath;
  117. std::string shaderName;
  118. std::string shaderExt;
  119. splitPath(getName(), shaderPath, shaderName, shaderExt);
  120. mIsSM3 = (shaderExt.find('3') != std::string::npos);
  121. // Take the first part of the shader name (shader group)
  122. size_t index = 2;
  123. while ((index < shaderName.length()) && (shaderName[index] != '_'))
  124. index++;
  125. std::string shaderGroup = shaderName.substr(0, index);
  126. // Load shader information XML file
  127. XMLFile* file = cache->getResource<XMLFile>(shaderPath + shaderGroup + ".xml");
  128. if (!file)
  129. return;
  130. // Update (global) parameter register mappings
  131. XMLElement shadersElem = file->getRootElement();
  132. XMLElement paramsElem = shadersElem.getChildElement("psparameters");
  133. XMLElement paramElem = paramsElem.getChildElement("parameter");
  134. while (paramElem)
  135. {
  136. std::string name = paramElem.getString("name");
  137. if (sParameters.find(name) == sParameters.end())
  138. LOGERROR("Unknown pixel shader parameter " + name + " in " + getName());
  139. else
  140. sRegisters[sParameters[name]] = paramElem.getInt("index");
  141. paramElem = paramElem.getNextElement("parameter");
  142. }
  143. // Get parameters and texture units used by this shader
  144. XMLElement shaderElem = shadersElem.getChildElement("shader");
  145. while (shaderElem)
  146. {
  147. std::string name = shaderElem.getString("name");
  148. std::string type = shaderElem.getStringLower("type");
  149. if ((name == shaderName) && (type == "ps"))
  150. {
  151. for (unsigned i = 0; i < MAX_PS_PARAMETERS; ++i)
  152. mUseParameter[i] = false;
  153. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  154. mUseTextureUnit[i] = false;
  155. XMLElement shaderParamElem = shaderElem.getChildElement("parameter");
  156. while (shaderParamElem)
  157. {
  158. std::string name = shaderParamElem.getString("name");
  159. mUseParameter[sParameters[name]] = true;
  160. shaderParamElem = shaderParamElem.getNextElement("parameter");
  161. }
  162. XMLElement textureElem = shaderElem.getChildElement("textureunit");
  163. while (textureElem)
  164. {
  165. std::string name = textureElem.getString("name");
  166. if (sTextureUnits.find(name) == sTextureUnits.end())
  167. LOGERROR("Unknown texture unit " + name + " in " + getName());
  168. else
  169. mUseTextureUnit[sTextureUnits[name]] = true;
  170. textureElem = textureElem.getNextElement("textureunit");
  171. }
  172. return;
  173. }
  174. shaderElem = shaderElem.getNextElement("shader");
  175. }
  176. LOGERROR("Shader " + shaderName + " not found in shader description XML file");
  177. }
  178. void PixelShader::initializeParameters()
  179. {
  180. if (sInitialized)
  181. return;
  182. // Initialize all parameters as unknown
  183. for (unsigned i = 0; i < MAX_PS_PARAMETERS; ++i)
  184. sRegisters[i] = MAX_CONSTANT_REGISTERS;
  185. // Map parameter names
  186. sParameters["AmbientColorPS"] = PSP_AMBIENTCOLOR;
  187. sParameters["DepthReconstruct"] = PSP_DEPTHRECONSTRUCT;
  188. sParameters["EdgeFilterParams"] = PSP_EDGEFILTERPARAMS;
  189. sParameters["ElapsedTimePS"] = PSP_ELAPSEDTIME;
  190. sParameters["FogColor"] = PSP_FOGCOLOR;
  191. sParameters["FogParams"] = PSP_FOGPARAMS;
  192. sParameters["LightAtten"] = PSP_LIGHTATTEN;
  193. sParameters["LightColor"] = PSP_LIGHTCOLOR;
  194. sParameters["LightDir"] = PSP_LIGHTDIR;
  195. sParameters["LightPos"] = PSP_LIGHTPOS;
  196. sParameters["LightSplits"] = PSP_LIGHTSPLITS;
  197. sParameters["MatDiffColor"] = PSP_MATDIFFCOLOR;
  198. sParameters["MatEmissiveColor"] = PSP_MATEMISSIVECOLOR;
  199. sParameters["MatSpecProperties"] = PSP_MATSPECPROPERTIES;
  200. sParameters["SampleOffsets"] = PSP_SAMPLEOFFSETS;
  201. sParameters["ShadowIntensity"] = PSP_SHADOWINTENSITY;
  202. sParameters["ShadowProjPS"] = PSP_SHADOWPROJ;
  203. sParameters["SpotProjPS"] = PSP_SPOTPROJ;
  204. // Map texture units
  205. sTextureUnits["NormalMap"] = TU_NORMAL;
  206. sTextureUnits["DiffMap"] = TU_DIFFUSE;
  207. sTextureUnits["DiffCubeMap"] = TU_DIFFUSE;
  208. sTextureUnits["SpecMap"] = TU_SPECULAR;
  209. sTextureUnits["EmissiveMap"] = TU_EMISSIVE;
  210. sTextureUnits["DetailMap"] = TU_DETAIL;
  211. sTextureUnits["EnvironmentMap"] = TU_ENVIRONMENT;
  212. sTextureUnits["EnvironmentCubeMap"] = TU_ENVIRONMENT;
  213. sTextureUnits["LightRampMap"] = TU_LIGHTRAMP;
  214. sTextureUnits["LightSpotMap"] = TU_LIGHTSPOT;
  215. sTextureUnits["LightCubeMap"] = TU_LIGHTSPOT;
  216. sTextureUnits["ShadowMap"] = TU_SHADOWMAP;
  217. sTextureUnits["DiffBuffer"] = TU_DIFFBUFFER;
  218. sTextureUnits["NormalBuffer"] = TU_NORMALBUFFER;
  219. sTextureUnits["DepthBuffer"] = TU_DEPTHBUFFER;
  220. sTextureUnits["LightBuffer"] = TU_LIGHTBUFFER;
  221. sInitialized = true;
  222. }