Shader.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. context->PSSetConstantBuffers(i, 1, &buf);
  139. }
  140. if (pixelShader) context->PSSetShader(pixelShader, 0, 0);
  141. }
  142. // Contents of the VertexShader class
  143. // Constructor
  144. DX11VertexShader::DX11VertexShader(
  145. ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock)
  146. : DX11Shader(device, context, deviceLock)
  147. {
  148. vertexShader = 0;
  149. inputLayout = 0;
  150. shaderByteBuffer = 0;
  151. byteBufferSize = 0;
  152. }
  153. // Destructor
  154. DX11VertexShader::~DX11VertexShader()
  155. {
  156. if (vertexShader) vertexShader->Release();
  157. if (inputLayout) inputLayout->Release();
  158. }
  159. // Sets the compiled shader
  160. // bytes: The bytes of the compiled code
  161. // length: the length of the byte array
  162. // return: true if bytes is valid, false otherwise
  163. bool DX11VertexShader::setCompiledByteArray(unsigned char* bytes, int length)
  164. {
  165. shaderByteBuffer = (unsigned char*)bytes;
  166. byteBufferSize = length;
  167. deviceLock.lock();
  168. HRESULT result
  169. = device->CreateVertexShader(bytes, length, 0, &vertexShader);
  170. deviceLock.unlock();
  171. return result == S_OK;
  172. }
  173. // Creates an InputLayout for the shader
  174. // Must only be called after compile
  175. // zD3d11Device: The device used to create the layout
  176. // descArray: An array with initialization data
  177. // anz: The number of elements in the array
  178. bool DX11VertexShader::createInputLayout(
  179. D3D11_INPUT_ELEMENT_DESC* descArray, int anz)
  180. {
  181. if (!shaderByteBuffer) return 0;
  182. if (inputLayout) inputLayout->Release();
  183. inputLayout = 0;
  184. deviceLock.lock();
  185. HRESULT res = device->CreateInputLayout(
  186. descArray, anz, shaderByteBuffer, byteBufferSize, &inputLayout);
  187. deviceLock.unlock();
  188. if (res == S_OK)
  189. {
  190. shaderByteBuffer = 0;
  191. byteBufferSize = 0;
  192. }
  193. return res == S_OK;
  194. }
  195. // After calling this function, this shader is used as vertex shader
  196. // zD3d11Context: The context object used with the shader
  197. void DX11VertexShader::useShader()
  198. {
  199. int maxI = constBuffers->getLastIndex();
  200. for (int i = 0; i <= maxI; i++)
  201. {
  202. if (!constBuffers->z(i)) continue;
  203. if (!((DX11Buffer*)constBuffers->z(i))->zBuffer())
  204. constBuffers->z(i)->copyToGPU();
  205. ID3D11Buffer* buf = ((DX11Buffer*)constBuffers->z(i))->zBuffer();
  206. context->VSSetConstantBuffers(i, 1, &buf);
  207. }
  208. if (inputLayout) context->IASetInputLayout(inputLayout);
  209. if (vertexShader) context->VSSetShader(vertexShader, 0, 0);
  210. }