Shader.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "Shader.h"
  2. #include <d3d11.h>
  3. #include <d3d12.h>
  4. #include <iostream>
  5. #include "DXBuffer.h"
  6. #include "File.h"
  7. #include "Text.h"
  8. using namespace Framework;
  9. // Contents of the Shader class
  10. // Constructor
  11. Shader::Shader()
  12. : ReferenceCounter()
  13. {
  14. type = UNBEKANNT;
  15. constBuffers = new RCArray<DXBuffer>();
  16. }
  17. // Destructor
  18. Shader::~Shader()
  19. {
  20. constBuffers->release();
  21. }
  22. // Deletes a constant buffer
  23. // index: the index of the buffer to be deleted. Buffer 0 cannot
  24. // be deleted while buffer 1 still exists, etc.
  25. bool Shader::removeConstBuffer(int index)
  26. {
  27. if (index < 0) return 0;
  28. bool ok = 1;
  29. constBuffers->set(0, index);
  30. return 1;
  31. }
  32. // Copies data into a constant buffer
  33. // zD3d11Context: The context object used for copying
  34. // data: A pointer to a byte array the size of the buffer
  35. // index: The index of the buffer
  36. // laen: The length of the data in bytes (-1 for the maximum size of the
  37. // buffer)
  38. bool Shader::fillConstBuffer(char* data, int index, int len)
  39. {
  40. if (index < 0 || index > constBuffers->getLastIndex()) return 0;
  41. DXBuffer* zB = constBuffers->z(index);
  42. if (!zB) return 0;
  43. if (len < 0) len = zB->getElementCount() * zB->getElementLength();
  44. zB->setData(data);
  45. zB->copyToGPU(len);
  46. return 1;
  47. }
  48. // Returns the length of a constant buffer
  49. // index: The index of the buffer
  50. int Shader::getConstBufferLaenge(int index) const
  51. {
  52. if (index < 0 || index > constBuffers->getLastIndex()) return 0;
  53. DXBuffer* zB = constBuffers->z(index);
  54. if (!zB) return 0;
  55. return zB->getElementCount() * zB->getElementLength();
  56. }
  57. // Returns the shader type
  58. ShaderType Shader::getType() const
  59. {
  60. return type;
  61. }
  62. //! Returns the index of the first uninitialized buffer
  63. int Shader::getFirstUninitializedBufferIndex() const
  64. {
  65. for (int index = 0; index < constBuffers->getEntryCount(); index++)
  66. {
  67. if (!constBuffers->has(index) || !constBuffers->z(index)) return index;
  68. }
  69. return constBuffers->getEntryCount();
  70. }
  71. DX11Shader::DX11Shader(
  72. ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
  73. : Shader(),
  74. deviceLock(deviceLock)
  75. {
  76. this->device = device;
  77. this->context = context;
  78. }
  79. DX11Shader::~DX11Shader() {}
  80. // Creates a constant buffer that passes constant data to the shader
  81. // A maximum of 14 buffers can be created
  82. // zD3d11Device: The device used to create the buffer
  83. // groesse: The size of the buffer in bytes
  84. // index: The position of the buffer in the buffer array. Existing buffer
  85. // is replaced. Buffer 1 cannot be created if buffer 0 has not yet
  86. // been created, etc.
  87. bool DX11Shader::createConstBuffer(int groesse, int index)
  88. {
  89. if (index < 0 || index >= 14) return 0;
  90. bool ok = 1;
  91. while ((groesse / 16) * 16
  92. != groesse) // only multiples of 16 are allowed as size
  93. groesse++;
  94. while (!constBuffers->has(index))
  95. constBuffers->add(0);
  96. constBuffers->set(
  97. new DX11Buffer(
  98. 1, device, context, D3D11_BIND_CONSTANT_BUFFER, deviceLock),
  99. index);
  100. constBuffers->z(index)->setLength(groesse);
  101. return 1;
  102. }
  103. // Contents of the PixelShader class
  104. // Constructor
  105. DX11PixelShader::DX11PixelShader(
  106. ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
  107. : DX11Shader(device, context, deviceLock)
  108. {
  109. pixelShader = 0;
  110. }
  111. // Destructor
  112. DX11PixelShader::~DX11PixelShader()
  113. {
  114. if (pixelShader) pixelShader->Release();
  115. }
  116. // Sets the compiled shader
  117. // bytes: The bytes of the compiled code
  118. // length: the length of the byte array
  119. // return: true if bytes is valid, false otherwise
  120. bool DX11PixelShader::setCompiledByteArray(unsigned char* bytes, int length)
  121. {
  122. deviceLock.lock();
  123. HRESULT result = device->CreatePixelShader(bytes, length, 0, &pixelShader);
  124. deviceLock.unlock();
  125. return result == S_OK;
  126. }
  127. // After calling this function, this shader is used as pixel shader
  128. // zD3d11Context: The context object used with the shader
  129. void DX11PixelShader::useShader()
  130. {
  131. int maxI = constBuffers->getLastIndex();
  132. for (int i = 0; i <= maxI; i++)
  133. {
  134. if (!constBuffers->z(i)) continue;
  135. if (!((DX11Buffer*)constBuffers->z(i))->zBuffer())
  136. constBuffers->z(i)->copyToGPU();
  137. ID3D11Buffer* buf = ((DX11Buffer*)constBuffers->z(i))->zBuffer();
  138. deviceLock.lock();
  139. context->PSSetConstantBuffers(i, 1, &buf);
  140. deviceLock.unlock();
  141. }
  142. if (pixelShader)
  143. {
  144. deviceLock.lock();
  145. context->PSSetShader(pixelShader, 0, 0);
  146. deviceLock.unlock();
  147. }
  148. }
  149. // Contents of the VertexShader class
  150. // Constructor
  151. DX11VertexShader::DX11VertexShader(
  152. ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
  153. : DX11Shader(device, context, deviceLock)
  154. {
  155. vertexShader = 0;
  156. inputLayout = 0;
  157. shaderByteBuffer = 0;
  158. byteBufferSize = 0;
  159. }
  160. // Destructor
  161. DX11VertexShader::~DX11VertexShader()
  162. {
  163. if (vertexShader) vertexShader->Release();
  164. if (inputLayout) inputLayout->Release();
  165. }
  166. // Sets the compiled shader
  167. // bytes: The bytes of the compiled code
  168. // length: the length of the byte array
  169. // return: true if bytes is valid, false otherwise
  170. bool DX11VertexShader::setCompiledByteArray(unsigned char* bytes, int length)
  171. {
  172. shaderByteBuffer = (unsigned char*)bytes;
  173. byteBufferSize = length;
  174. deviceLock.lock();
  175. HRESULT result
  176. = device->CreateVertexShader(bytes, length, 0, &vertexShader);
  177. deviceLock.unlock();
  178. return result == S_OK;
  179. }
  180. // Creates an InputLayout for the shader
  181. // Must only be called after compile
  182. // zD3d11Device: The device used to create the layout
  183. // descArray: An array with initialization data
  184. // anz: The number of elements in the array
  185. bool DX11VertexShader::createInputLayout(
  186. D3D11_INPUT_ELEMENT_DESC* descArray, int anz)
  187. {
  188. if (!shaderByteBuffer) return 0;
  189. if (inputLayout) inputLayout->Release();
  190. inputLayout = 0;
  191. deviceLock.lock();
  192. HRESULT res = device->CreateInputLayout(
  193. descArray, anz, shaderByteBuffer, byteBufferSize, &inputLayout);
  194. deviceLock.unlock();
  195. if (res == S_OK)
  196. {
  197. shaderByteBuffer = 0;
  198. byteBufferSize = 0;
  199. }
  200. return res == S_OK;
  201. }
  202. // After calling this function, this shader is used as vertex shader
  203. // zD3d11Context: The context object used with the shader
  204. void DX11VertexShader::useShader()
  205. {
  206. int maxI = constBuffers->getLastIndex();
  207. for (int i = 0; i <= maxI; i++)
  208. {
  209. if (!constBuffers->z(i)) continue;
  210. if (!((DX11Buffer*)constBuffers->z(i))->zBuffer())
  211. constBuffers->z(i)->copyToGPU();
  212. ID3D11Buffer* buf = ((DX11Buffer*)constBuffers->z(i))->zBuffer();
  213. deviceLock.lock();
  214. context->VSSetConstantBuffers(i, 1, &buf);
  215. deviceLock.unlock();
  216. }
  217. if (inputLayout)
  218. {
  219. deviceLock.lock();
  220. context->IASetInputLayout(inputLayout);
  221. deviceLock.unlock();
  222. }
  223. if (vertexShader)
  224. {
  225. deviceLock.lock();
  226. context->VSSetShader(vertexShader, 0, 0);
  227. deviceLock.unlock();
  228. }
  229. }