ShaderCompiler.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  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 "Context.h"
  24. #include "File.h"
  25. #include "FileSystem.h"
  26. #include "ProcessUtils.h"
  27. #include "StringUtils.h"
  28. #include "XMLFile.h"
  29. #include <cstdio>
  30. #include <cstring>
  31. #include <Windows.h>
  32. #include <d3d9.h>
  33. #include <D3DX9Shader.h>
  34. #include "DebugNew.h"
  35. enum ShaderType
  36. {
  37. VS,
  38. PS,
  39. Both
  40. };
  41. struct Variation
  42. {
  43. Variation()
  44. {
  45. }
  46. Variation(const String& name, bool isOption) :
  47. name_(name),
  48. option_(isOption)
  49. {
  50. }
  51. void AddDefine(const String& def)
  52. {
  53. defines_.Push(def);
  54. }
  55. void AddExclude(const String& excl)
  56. {
  57. excludes_.Push(excl);
  58. }
  59. void AddInclude(const String& incl)
  60. {
  61. includes_.Push(incl);
  62. }
  63. void AddRequire(const String& req)
  64. {
  65. requires_.Push(req);
  66. }
  67. String name_;
  68. Vector<String> defines_;
  69. Vector<String> excludes_;
  70. Vector<String> includes_;
  71. Vector<String> requires_;
  72. bool option_;
  73. };
  74. struct Shader
  75. {
  76. Shader(const String& name, ShaderType type) :
  77. name_(name),
  78. type_(type)
  79. {
  80. }
  81. void AddVariation(const Variation& var)
  82. {
  83. variations_.Push(var);
  84. }
  85. String name_;
  86. ShaderType type_;
  87. Vector<Variation> variations_;
  88. };
  89. struct Parameter
  90. {
  91. String name_;
  92. unsigned index_;
  93. };
  94. struct Parameters
  95. {
  96. void AddVSParam(const String& name, unsigned index)
  97. {
  98. Parameter newParam;
  99. newParam.name_ = name;
  100. newParam.index_ = index;
  101. vsParams_.Push(newParam);
  102. }
  103. void AddPSParam(const String& name, unsigned index)
  104. {
  105. Parameter newParam;
  106. newParam.name_ = name;
  107. newParam.index_ = index;
  108. psParams_.Push(newParam);
  109. }
  110. void AddTextureUnit(const String& name, unsigned index)
  111. {
  112. Parameter newParam;
  113. newParam.name_ = name;
  114. newParam.index_ = index;
  115. textureUnits_.Push(newParam);
  116. }
  117. Vector<Parameter> vsParams_;
  118. Vector<Parameter> psParams_;
  119. Vector<Parameter> textureUnits_;
  120. };
  121. SharedPtr<Context> context_(new Context());
  122. SharedPtr<FileSystem> fileSystem_(new FileSystem(context_));
  123. String inDir_;
  124. String inFile_;
  125. String outDir_;
  126. Map<String, unsigned> vsParams_;
  127. Map<String, unsigned> psParams_;
  128. Map<String, unsigned> textureUnits_;
  129. Vector<String> defines_;
  130. bool useSM3_ = false;
  131. int main(int argc, char** argv);
  132. void Run(const Vector<String>& arguments);
  133. void CompileVariations(const Shader& baseShader, XMLElement& shaders);
  134. bool Compile(ShaderType type, const String& hlslCode, const String& output, const Vector<String>& defines, Parameters& params);
  135. class IncludeHandler : public ID3DXInclude
  136. {
  137. public:
  138. STDMETHOD(Open)(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
  139. {
  140. String fileName = inDir_ + String((const char*)pFileName);
  141. SharedPtr<File> file(new File(context_, fileName));
  142. if (!file->IsOpen())
  143. return E_FAIL;
  144. unsigned fileSize = file->GetSize();
  145. void* fileData = new unsigned char[fileSize];
  146. *pBytes = fileSize;
  147. *ppData = fileData;
  148. file->Read(fileData, fileSize);
  149. return S_OK;
  150. }
  151. STDMETHOD(Close)(LPCVOID pData)
  152. {
  153. delete[] (unsigned char*)pData;
  154. return S_OK;
  155. }
  156. };
  157. int main(int argc, char** argv)
  158. {
  159. Vector<String> arguments;
  160. for (int i = 1; i < argc; ++i)
  161. {
  162. String argument(argv[i]);
  163. arguments.Push(argument.Replace('/', '\\'));
  164. }
  165. Run(arguments);
  166. return 0;
  167. }
  168. void Run(const Vector<String>& arguments)
  169. {
  170. if (arguments.Size() < 2)
  171. {
  172. ErrorExit(
  173. "Usage: ShaderCompiler <definitionfile> <outputpath> [SM3] [define1] [define2]\n\n"
  174. "HLSL files will be loaded from definition file directory, and binary code will\n"
  175. "be output to same directory as the output file.\n"
  176. );
  177. }
  178. unsigned pos = arguments[0].FindLast('\\');
  179. if (pos != String::NPOS)
  180. {
  181. inDir_ = arguments[0].Substring(0, pos);
  182. inFile_ = arguments[0].Substring(pos + 1);
  183. }
  184. else
  185. {
  186. inFile_ = arguments[0];
  187. }
  188. outDir_ = arguments[1];
  189. inDir_ = AddTrailingSlash(inDir_);
  190. outDir_ = AddTrailingSlash(outDir_);
  191. for (unsigned i = 2; i < arguments.Size(); ++i)
  192. {
  193. String arg = arguments[i].ToUpper();
  194. if (arg == "SM3")
  195. useSM3_ = true;
  196. else if (arg == "SM2")
  197. useSM3_ = false;
  198. defines_.Push(arg);
  199. }
  200. XMLFile doc(context_);
  201. File source(context_);
  202. source.Open(arguments[0]);
  203. if (!doc.Load(source))
  204. ErrorExit("Could not open input file " + arguments[0]);
  205. XMLElement shaders = doc.GetRootElement("shaders");
  206. if (!shaders)
  207. ErrorExit("No shaders element in " + source.GetName());
  208. XMLFile outDoc(context_);
  209. XMLElement outShaders = outDoc.CreateRootElement("shaders");
  210. XMLElement shader = shaders.GetChildElement("shader");
  211. while (shader)
  212. {
  213. bool WriteOutput = false;
  214. String source = shader.GetString("name");
  215. ShaderType compileType = Both;
  216. String type = shader.GetString("type");
  217. if ((type == "VS") || (type == "vs"))
  218. compileType = VS;
  219. if ((type == "PS") || (type == "ps"))
  220. compileType = PS;
  221. if ((compileType == Both) || (compileType == PS))
  222. WriteOutput = true;
  223. Shader baseShader(source, compileType);
  224. XMLElement variation = shader.GetChildElement("");
  225. while (variation)
  226. {
  227. String value = variation.GetName();
  228. if ((value == "variation") || (value == "option"))
  229. {
  230. String name = variation.GetString("name");
  231. Variation newVar(name, value == "option");
  232. String simpleDefine = variation.GetString("define");
  233. if (!simpleDefine.Empty())
  234. newVar.AddDefine(simpleDefine);
  235. String simpleExclude = variation.GetString("exclude");
  236. if (!simpleExclude.Empty())
  237. newVar.AddExclude(simpleExclude);
  238. String simpleInclude = variation.GetString("include");
  239. if (!simpleInclude.Empty())
  240. newVar.AddInclude(simpleInclude);
  241. String simpleRequire = variation.GetString("require");
  242. if (!simpleRequire.Empty())
  243. newVar.AddRequire(simpleRequire);
  244. XMLElement define = variation.GetChildElement("define");
  245. while (define)
  246. {
  247. String name = define.GetString("name");
  248. newVar.AddDefine(name);
  249. define = define.GetNextElement("define");
  250. }
  251. XMLElement exclude = variation.GetChildElement("exclude");
  252. while (exclude)
  253. {
  254. String name = exclude.GetString("name");
  255. newVar.AddExclude(name);
  256. exclude = exclude.GetNextElement("exclude");
  257. }
  258. XMLElement include = variation.GetChildElement("include");
  259. while (include)
  260. {
  261. String name = include.GetString("name");
  262. newVar.AddInclude(name);
  263. include = include.GetNextElement("include");
  264. }
  265. XMLElement require = variation.GetChildElement("require");
  266. while (require)
  267. {
  268. String name = require.GetString("name");
  269. newVar.AddRequire(name);
  270. require = require.GetNextElement("require");
  271. }
  272. baseShader.AddVariation(newVar);
  273. }
  274. variation = variation.GetNextElement();
  275. }
  276. if (baseShader.type_ != Both)
  277. CompileVariations(baseShader, outShaders);
  278. else
  279. {
  280. baseShader.type_ = VS;
  281. CompileVariations(baseShader, outShaders);
  282. baseShader.type_ = PS;
  283. CompileVariations(baseShader, outShaders);
  284. }
  285. if (WriteOutput)
  286. {
  287. String outFileName = outDir_ + inDir_ + source + ".xml";
  288. remove(outFileName.CString());
  289. // Add global parameter & texture sampler definitions
  290. {
  291. XMLElement parameters = outShaders.CreateChildElement("vsparameters");
  292. Map<unsigned, Vector<String> > sorted;
  293. for (Map<String, unsigned>::ConstIterator i = vsParams_.Begin(); i != vsParams_.End(); ++i)
  294. sorted[i->second_].Push(i->first_);
  295. for (Map<unsigned, Vector<String> >::ConstIterator i = sorted.Begin(); i != sorted.End(); ++i)
  296. {
  297. for (unsigned j = 0; j < i->second_.Size(); ++j)
  298. {
  299. XMLElement param = parameters.CreateChildElement("parameter");
  300. param.SetString("name", i->second_[j]);
  301. param.SetInt("index", i->first_);
  302. }
  303. }
  304. }
  305. {
  306. XMLElement parameters = outShaders.CreateChildElement("psparameters");
  307. Map<unsigned, Vector<String> > sorted;
  308. for (Map<String, unsigned>::ConstIterator i = psParams_.Begin(); i != psParams_.End(); ++i)
  309. sorted[i->second_].Push(i->first_);
  310. for (Map<unsigned, Vector<String> >::ConstIterator i = sorted.Begin(); i != sorted.End(); ++i)
  311. {
  312. for (unsigned j = 0; j < i->second_.Size(); ++j)
  313. {
  314. XMLElement param = parameters.CreateChildElement("parameter");
  315. param.SetString("name", i->second_[j]);
  316. param.SetInt("index", i->first_);
  317. }
  318. }
  319. }
  320. {
  321. XMLElement parameters = outShaders.CreateChildElement("textureunits");
  322. Map<unsigned, Vector<String> > sorted;
  323. for (Map<String, unsigned>::ConstIterator i = textureUnits_.Begin(); i != textureUnits_.End(); ++i)
  324. sorted[i->second_].Push(i->first_);
  325. for (Map<unsigned, Vector<String> >::ConstIterator i = sorted.Begin(); i != sorted.End(); ++i)
  326. {
  327. for (unsigned j = 0; j < i->second_.Size(); ++j)
  328. {
  329. XMLElement param = parameters.CreateChildElement("parameter");
  330. param.SetString("name", i->second_[j]);
  331. param.SetInt("index", i->first_);
  332. }
  333. }
  334. }
  335. File outFile(context_);
  336. outFile.Open(outFileName, FILE_WRITE);
  337. if (!outDoc.Save(outFile))
  338. ErrorExit("Could not save output file " + outFileName);
  339. }
  340. shader = shader.GetNextElement("shader");
  341. }
  342. }
  343. void CompileVariations(const Shader& baseShader, XMLElement& shaders)
  344. {
  345. unsigned combinations = 1;
  346. PODVector<unsigned> compiled;
  347. bool hasVariations = false;
  348. Map<String, unsigned> nameToIndex;
  349. String hlslCode;
  350. const Vector<Variation>& variations = baseShader.variations_;
  351. if (variations.Size() > 32)
  352. ErrorExit("Maximum amount of variations exceeded");
  353. // Load the shader source code
  354. String inputFileName = inDir_ + baseShader.name_ + ".hlsl";
  355. SharedPtr<File> hlslFile(new File(context_, inputFileName));
  356. if (!hlslFile->IsOpen())
  357. ErrorExit("Could not open input file " + inputFileName);
  358. while (!hlslFile->IsEof())
  359. hlslCode += hlslFile->ReadLine() + "\n";
  360. hlslFile->Close();
  361. for (unsigned i = 0; i < variations.Size(); ++i)
  362. {
  363. combinations *= 2;
  364. nameToIndex[variations[i].name_] = i;
  365. if (!variations[i].option_)
  366. hasVariations = true;
  367. }
  368. for (unsigned i = 0; i < combinations; ++i)
  369. {
  370. unsigned active = i; // Variations/options active on this particular combination
  371. bool variationActive = false;
  372. bool skipThis = false;
  373. // Check for excludes/includes/requires
  374. for (unsigned j = 0; j < variations.Size(); ++j)
  375. {
  376. if ((active >> j) & 1)
  377. {
  378. for (unsigned k = 0; k < variations[j].includes_.Size(); ++k)
  379. {
  380. if (nameToIndex.Find(variations[j].includes_[k]) != nameToIndex.End())
  381. active |= (1 << nameToIndex[variations[j].includes_[k]]);
  382. }
  383. for (unsigned k = 0; k < variations[j].excludes_.Size(); ++k)
  384. {
  385. if (nameToIndex.Find(variations[j].excludes_[k]) != nameToIndex.End())
  386. active &= ~(1 << nameToIndex[variations[j].excludes_[k]]);
  387. }
  388. // If it's a variation, exclude all other variations
  389. if (!variations[j].option_)
  390. {
  391. for (unsigned k = 0; k < variations.Size(); ++k)
  392. {
  393. if ((k != j) && (!variations[k].option_))
  394. active &= ~(1 << k);
  395. }
  396. variationActive = true;
  397. }
  398. for (unsigned k = 0; k < variations[j].requires_.Size(); ++k)
  399. {
  400. bool requireFound = false;
  401. for (unsigned l = 0; l < defines_.Size(); ++l)
  402. {
  403. if (defines_[l] == variations[j].requires_[k])
  404. {
  405. requireFound = true;
  406. break;
  407. }
  408. }
  409. for (unsigned l = 0; l < variations.Size(); ++l)
  410. {
  411. if (((active >> l) & 1) && (l != j))
  412. {
  413. if (variations[l].name_ == variations[j].requires_[k])
  414. {
  415. requireFound = true;
  416. break;
  417. }
  418. for (unsigned m = 0; m < variations[l].defines_.Size(); ++m)
  419. {
  420. if (variations[l].defines_[m] == variations[j].requires_[k])
  421. {
  422. requireFound = true;
  423. break;
  424. }
  425. }
  426. }
  427. if (requireFound)
  428. break;
  429. }
  430. if (!requireFound)
  431. skipThis = true;
  432. }
  433. }
  434. }
  435. // If variations are included, check that one of them is active
  436. if ((hasVariations) && (!variationActive))
  437. continue;
  438. if (skipThis)
  439. continue;
  440. // Check that this combination is unique
  441. bool unique = true;
  442. for (unsigned j = 0; j < compiled.Size(); ++j)
  443. {
  444. if (compiled[j] == active)
  445. {
  446. unique = false;
  447. break;
  448. }
  449. }
  450. if (unique)
  451. {
  452. bool firstSuffix = true;
  453. // Build output shader filename & defines from active variations
  454. String outName = baseShader.name_;
  455. Vector<String> defines;
  456. for (unsigned j = 0; j < variations.Size(); ++j)
  457. {
  458. if (active & (1 << j))
  459. {
  460. if (variations[j].name_.Length())
  461. {
  462. if (firstSuffix)
  463. {
  464. outName = outName + "_" + variations[j].name_;
  465. firstSuffix = false;
  466. }
  467. else
  468. outName = outName + variations[j].name_;
  469. }
  470. for (unsigned k = 0; k < variations[j].defines_.Size(); ++k)
  471. defines.Push(variations[j].defines_[k]);
  472. }
  473. }
  474. Parameters params;
  475. bool ok = Compile(baseShader.type_, hlslCode, outName, defines, params);
  476. // If shader was unnecessary (for example SM2 does not support HQ variations)
  477. // no output may have been produced. Skip in that case.
  478. if (ok)
  479. {
  480. XMLElement shader = shaders.CreateChildElement("shader");
  481. shader.SetString("name", outName);
  482. switch (baseShader.type_)
  483. {
  484. case VS:
  485. shader.SetString("type", "vs");
  486. for (unsigned j = 0; j < params.vsParams_.Size(); ++j)
  487. {
  488. XMLElement vsParam = shader.CreateChildElement("parameter");
  489. vsParam.SetString("name", params.vsParams_[j].name_);
  490. }
  491. break;
  492. case PS:
  493. shader.SetString("type", "ps");
  494. for (unsigned j = 0; j < params.psParams_.Size(); ++j)
  495. {
  496. XMLElement psParam = shader.CreateChildElement("parameter");
  497. psParam.SetString("name", params.psParams_[j].name_);
  498. }
  499. for (unsigned j = 0; j < params.textureUnits_.Size(); ++j)
  500. {
  501. XMLElement texture = shader.CreateChildElement("textureunit");
  502. texture.SetString("name", params.textureUnits_[j].name_);
  503. }
  504. break;
  505. }
  506. compiled.Push(active);
  507. }
  508. }
  509. }
  510. }
  511. bool Compile(ShaderType type, const String& hlslCode, const String& output, const Vector<String>& defines,
  512. Parameters& params)
  513. {
  514. IncludeHandler includeHandler;
  515. PODVector<D3DXMACRO> macros;
  516. String value = "1";
  517. // Insert variation-specific and global defines
  518. for (unsigned i = 0; i < defines.Size(); ++i)
  519. {
  520. D3DXMACRO macro;
  521. macro.Name = defines[i].CString();
  522. macro.Definition = value.CString();
  523. macros.Push(macro);
  524. }
  525. for (unsigned i = 0; i < defines_.Size(); ++i)
  526. {
  527. D3DXMACRO macro;
  528. macro.Name = defines_[i].CString();
  529. macro.Definition = value.CString();
  530. macros.Push(macro);
  531. }
  532. D3DXMACRO endMacro;
  533. endMacro.Name = 0;
  534. endMacro.Definition = 0;
  535. macros.Push(endMacro);
  536. LPD3DXBUFFER shaderCode = 0;
  537. LPD3DXBUFFER errorMsgs = 0;
  538. LPD3DXCONSTANTTABLE constantTable = 0;
  539. // Set the profile, entrypoint and flags according to the shader being compiled
  540. String profile;
  541. String extension;
  542. String entryPoint;
  543. unsigned flags = D3DXSHADER_OPTIMIZATION_LEVEL3;
  544. if (type == VS)
  545. {
  546. entryPoint = "VS";
  547. if (!useSM3_)
  548. {
  549. profile = "vs_2_0";
  550. extension = ".vs2";
  551. }
  552. else
  553. {
  554. profile = "vs_3_0";
  555. extension = ".vs3";
  556. }
  557. }
  558. else
  559. {
  560. entryPoint = "PS";
  561. if (!useSM3_)
  562. {
  563. profile = "ps_2_0";
  564. extension = ".ps2";
  565. }
  566. else
  567. {
  568. profile = "ps_3_0";
  569. extension = ".ps3";
  570. flags |= D3DXSHADER_PREFER_FLOW_CONTROL;
  571. }
  572. }
  573. String outFileName = outDir_ + inDir_ + output + extension;
  574. // Compile using D3DX
  575. PrintLine("Compiling shader " + outFileName);
  576. HRESULT hr = D3DXCompileShader(hlslCode.CString(), hlslCode.Length(), &macros.Front(), &includeHandler,
  577. entryPoint.CString(), profile.CString(), flags, &shaderCode, &errorMsgs, &constantTable);
  578. if (FAILED(hr))
  579. {
  580. String error((const char*)errorMsgs->GetBufferPointer(), errorMsgs->GetBufferSize());
  581. errorMsgs->Release();
  582. ErrorExit("Failed to compile shader " + outFileName + ": " + error);
  583. }
  584. // Write the shader bytecode
  585. SharedPtr<File> outFile(new File(context_, outFileName, FILE_WRITE));
  586. if (outFile->IsOpen())
  587. outFile->Write(shaderCode->GetBufferPointer(), shaderCode->GetBufferSize());
  588. else
  589. ErrorExit("Failed to write output file " + outFileName);
  590. // Parse the constant table for constants and texture units
  591. D3DXCONSTANTTABLE_DESC desc;
  592. constantTable->GetDesc(&desc);
  593. for (unsigned i = 0; i < desc.Constants; ++i)
  594. {
  595. D3DXHANDLE handle = constantTable->GetConstant(NULL, i);
  596. D3DXCONSTANT_DESC constantDesc;
  597. unsigned numElements = 1;
  598. constantTable->GetConstantDesc(handle, &constantDesc, &numElements);
  599. String name(constantDesc.Name);
  600. unsigned index = constantDesc.RegisterIndex;
  601. // Check if the parameter is a constant or a texture sampler
  602. bool isSampler = (name[0] == 's');
  603. name = name.Substring(1);
  604. if (isSampler)
  605. {
  606. // Skip if it's a G-buffer sampler
  607. if (name.Find("Buffer") == String::NPOS)
  608. {
  609. params.AddTextureUnit(name, index);
  610. if (textureUnits_.Find(name) != textureUnits_.End())
  611. {
  612. unsigned oldIndex = textureUnits_[name];
  613. if (oldIndex != index)
  614. ErrorExit("Texture " + name + " bound to several sampler registers");
  615. }
  616. textureUnits_[name] = index;
  617. }
  618. }
  619. else
  620. {
  621. if (type == VS)
  622. {
  623. params.AddVSParam(name, index);
  624. if (vsParams_.Find(name) != vsParams_.End())
  625. {
  626. unsigned oldIndex = vsParams_[name];
  627. if (oldIndex != index)
  628. ErrorExit("Parameter " + name + " bound to several constant registers");
  629. }
  630. vsParams_[name] = index;
  631. }
  632. else
  633. {
  634. params.AddPSParam(name, index);
  635. if (psParams_.Find(name) != psParams_.End())
  636. {
  637. unsigned oldIndex = psParams_[name];
  638. if (oldIndex != index)
  639. ErrorExit("Parameter " + name + " bound to several constant registers");
  640. }
  641. psParams_[name] = index;
  642. }
  643. }
  644. }
  645. if (shaderCode)
  646. shaderCode->Release();
  647. if (constantTable)
  648. constantTable->Release();
  649. return true;
  650. }