BsD3D11RenderUtility.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "BsD3D11RenderUtility.h"
  2. #include "BsD3D11Device.h"
  3. #include "BsVector3.h"
  4. #include "BsColor.h"
  5. #include "BsRect2I.h"
  6. #include "BsD3D11BlendState.h"
  7. #include "BsD3D11RasterizerState.h"
  8. #include "BsD3D11DepthStencilState.h"
  9. namespace BansheeEngine
  10. {
  11. struct ClearVertex
  12. {
  13. Vector3 pos;
  14. UINT32 col;
  15. };
  16. D3D11RenderUtility::D3D11RenderUtility(D3D11Device* device)
  17. :mDevice(device), mClearQuadIB(nullptr), mClearQuadVB(nullptr),
  18. mClearQuadIL(nullptr), mClearQuadVS(nullptr), mClearQuadPS(nullptr)
  19. {
  20. initClearQuadResources();
  21. }
  22. D3D11RenderUtility::~D3D11RenderUtility()
  23. {
  24. SAFE_RELEASE(mClearQuadPS);
  25. SAFE_RELEASE(mClearQuadVS);
  26. SAFE_RELEASE(mClearQuadIL);
  27. SAFE_RELEASE(mClearQuadIB);
  28. SAFE_RELEASE(mClearQuadVB);
  29. }
  30. void D3D11RenderUtility::drawClearQuad(UINT32 clearBuffers, const Color& color, float depth, UINT16 stencil)
  31. {
  32. // Set states
  33. if((clearBuffers & FBT_COLOR) != 0)
  34. {
  35. D3D11BlendState* d3d11BlendState = static_cast<D3D11BlendState*>(const_cast<BlendState*>(mClearQuadBlendStateYesC.get()));
  36. mDevice->getImmediateContext()->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
  37. }
  38. else
  39. {
  40. D3D11BlendState* d3d11BlendState = static_cast<D3D11BlendState*>(const_cast<BlendState*>(mClearQuadBlendStateNoC.get()));
  41. mDevice->getImmediateContext()->OMSetBlendState(d3d11BlendState->getInternal(), nullptr, 0xFFFFFFFF);
  42. }
  43. D3D11RasterizerState* d3d11RasterizerState = static_cast<D3D11RasterizerState*>(const_cast<RasterizerState*>(mClearQuadRasterizerState.get()));
  44. mDevice->getImmediateContext()->RSSetState(d3d11RasterizerState->getInternal());
  45. if((clearBuffers & FBT_DEPTH) != 0)
  46. {
  47. if((clearBuffers & FBT_STENCIL) != 0)
  48. {
  49. D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateYesD_YesS.get()));
  50. mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
  51. }
  52. else
  53. {
  54. D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateYesD_NoS.get()));
  55. mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
  56. }
  57. }
  58. else
  59. {
  60. if((clearBuffers & FBT_STENCIL) != 0)
  61. {
  62. D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateNoD_YesS.get()));
  63. mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
  64. }
  65. else
  66. {
  67. D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateNoD_NoS.get()));
  68. mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
  69. }
  70. }
  71. // TODO - How smart it is to update buffer right before drawing it!? (cache the clip area)
  72. ClearVertex vertexData[4];
  73. vertexData[0].pos = Vector3(-1.0f, 1.0f, depth);
  74. vertexData[1].pos = Vector3(1.0f, 1.0f, depth);
  75. vertexData[2].pos = Vector3(-1.0f, -1.0f, depth);
  76. vertexData[3].pos = Vector3(1.0f, -1.0f, depth);
  77. vertexData[0].col = color.getAsRGBA();
  78. vertexData[1].col = color.getAsRGBA();
  79. vertexData[2].col = color.getAsRGBA();
  80. vertexData[3].col = color.getAsRGBA();
  81. mDevice->getImmediateContext()->UpdateSubresource(mClearQuadVB, 0, nullptr, vertexData, 0, sizeof(ClearVertex) * 4);
  82. mDevice->getImmediateContext()->VSSetShader(mClearQuadVS, nullptr, 0);
  83. mDevice->getImmediateContext()->PSSetShader(mClearQuadPS, nullptr, 0);
  84. ID3D11Buffer* buffers[1];
  85. buffers[0] = mClearQuadVB;
  86. UINT32 strides[1] = { sizeof(ClearVertex) };
  87. UINT32 offsets[1] = { 0 };
  88. mDevice->getImmediateContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  89. mDevice->getImmediateContext()->IASetIndexBuffer(mClearQuadIB, DXGI_FORMAT_R16_UINT, 0);
  90. mDevice->getImmediateContext()->IASetVertexBuffers(0, 1, buffers, strides, offsets);
  91. mDevice->getImmediateContext()->IASetInputLayout(mClearQuadIL);
  92. mDevice->getImmediateContext()->DrawIndexed(6, 0, 0);
  93. }
  94. void D3D11RenderUtility::initClearQuadResources()
  95. {
  96. BLEND_STATE_DESC blendStateDescYesC;
  97. mClearQuadBlendStateYesC = BlendState::create(blendStateDescYesC);
  98. BLEND_STATE_DESC blendStateDescNoC;
  99. for(int i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  100. blendStateDescNoC.renderTargetDesc[i].renderTargetWriteMask = 0;
  101. mClearQuadBlendStateNoC = BlendState::create(blendStateDescNoC);
  102. DEPTH_STENCIL_STATE_DESC depthStateDescNoD_NoS;
  103. depthStateDescNoD_NoS.depthReadEnable = false;
  104. depthStateDescNoD_NoS.depthWriteEnable = false;
  105. depthStateDescNoD_NoS.depthComparisonFunc = CMPF_ALWAYS_PASS;
  106. mClearQuadDSStateNoD_NoS = DepthStencilState::create(depthStateDescNoD_NoS);
  107. DEPTH_STENCIL_STATE_DESC depthStateDescYesD_NoS;
  108. depthStateDescYesD_NoS.depthReadEnable = false;
  109. depthStateDescYesD_NoS.depthWriteEnable = false; // TODO - Set to true
  110. //depthStateDescYesD_NoS.depthComparisonFunc = CMPF_ALWAYS_PASS;
  111. mClearQuadDSStateYesD_NoS = DepthStencilState::create(depthStateDescYesD_NoS);
  112. DEPTH_STENCIL_STATE_DESC depthStateDescYesD_YesS;
  113. depthStateDescYesD_YesS.depthReadEnable = false;
  114. depthStateDescYesD_YesS.depthWriteEnable = true;
  115. depthStateDescYesD_YesS.depthComparisonFunc = CMPF_ALWAYS_PASS;
  116. depthStateDescYesD_YesS.stencilEnable = true;
  117. depthStateDescYesD_YesS.frontStencilComparisonFunc = CMPF_ALWAYS_PASS;
  118. depthStateDescYesD_YesS.frontStencilPassOp = SOP_REPLACE;
  119. mClearQuadDSStateYesD_YesS = DepthStencilState::create(depthStateDescYesD_YesS);
  120. DEPTH_STENCIL_STATE_DESC depthStateDescNoD_YesS;
  121. depthStateDescNoD_YesS.depthReadEnable = false;
  122. depthStateDescNoD_YesS.depthWriteEnable = false;
  123. depthStateDescNoD_YesS.depthComparisonFunc = CMPF_ALWAYS_PASS;
  124. depthStateDescNoD_YesS.stencilEnable = true;
  125. depthStateDescNoD_YesS.frontStencilComparisonFunc = CMPF_ALWAYS_PASS;
  126. mClearQuadDSStateNoD_YesS = DepthStencilState::create(depthStateDescNoD_YesS);
  127. RASTERIZER_STATE_DESC rasterizerStateDesc;
  128. mClearQuadRasterizerState = RasterizerState::create(rasterizerStateDesc);
  129. String vsShaderCode = " \
  130. void main( \
  131. in float3 inPos : POSITION, \
  132. in float4 color : COLOR0, \
  133. out float4 oPosition : SV_Position, \
  134. out float4 oColor : COLOR0) \
  135. { \
  136. oPosition = float4(inPos.xyz, 1); \
  137. oColor = color; \
  138. } \
  139. ";
  140. String psShaderCode = "float4 main(in float4 inPos : SV_Position, float4 color : COLOR0) : SV_Target \
  141. { return color; }";
  142. HRESULT hr;
  143. ID3DBlob* microcode = nullptr;
  144. ID3DBlob* errors = nullptr;
  145. // Compile pixel shader
  146. hr = D3DCompile(psShaderCode.c_str(), psShaderCode.size(), nullptr, nullptr, nullptr, "main", "ps_4_0",
  147. D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR, 0, &microcode, &errors);
  148. if (FAILED(hr))
  149. {
  150. String message = "Cannot assemble D3D11 high-level shader. Errors:\n" +
  151. String(static_cast<const char*>(errors->GetBufferPointer()));
  152. SAFE_RELEASE(errors);
  153. BS_EXCEPT(RenderingAPIException, message);
  154. }
  155. SAFE_RELEASE(errors);
  156. hr = mDevice->getD3D11Device()->CreatePixelShader(static_cast<DWORD*>(microcode->GetBufferPointer()),
  157. microcode->GetBufferSize(), mDevice->getClassLinkage(), &mClearQuadPS);
  158. if (FAILED(hr))
  159. {
  160. SAFE_RELEASE(microcode);
  161. BS_EXCEPT(RenderingAPIException, "Cannot create D3D11 high-level shader.");
  162. }
  163. // Compile vertex shader
  164. hr = D3DCompile(vsShaderCode.c_str(), vsShaderCode.size(), nullptr, nullptr, nullptr, "main", "vs_4_0",
  165. D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR, 0, &microcode, &errors);
  166. if (FAILED(hr))
  167. {
  168. String message = "Cannot assemble D3D11 high-level shader. Errors:\n" +
  169. String(static_cast<const char*>(errors->GetBufferPointer()));
  170. SAFE_RELEASE(errors);
  171. BS_EXCEPT(RenderingAPIException, message);
  172. }
  173. SAFE_RELEASE(errors);
  174. hr = mDevice->getD3D11Device()->CreateVertexShader(static_cast<DWORD*>(microcode->GetBufferPointer()),
  175. microcode->GetBufferSize(), mDevice->getClassLinkage(), &mClearQuadVS);
  176. if (FAILED(hr))
  177. {
  178. SAFE_RELEASE(microcode);
  179. BS_EXCEPT(RenderingAPIException, "Cannot create D3D11 high-level shader.");
  180. }
  181. // Create input layout
  182. D3D11_INPUT_ELEMENT_DESC* declElements = bs_newN<D3D11_INPUT_ELEMENT_DESC, ScratchAlloc>(2);
  183. ZeroMemory(declElements, sizeof(D3D11_INPUT_ELEMENT_DESC) * 2);
  184. declElements[0].SemanticName = "POSITION";
  185. declElements[0].SemanticIndex = 0;
  186. declElements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
  187. declElements[0].InputSlot = 0;
  188. declElements[0].AlignedByteOffset = 0;
  189. declElements[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
  190. declElements[0].InstanceDataStepRate = 0;
  191. declElements[1].SemanticName = "COLOR";
  192. declElements[1].SemanticIndex = 0;
  193. declElements[1].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  194. declElements[1].InputSlot = 0;
  195. declElements[1].AlignedByteOffset = sizeof(float) * 3;
  196. declElements[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
  197. declElements[1].InstanceDataStepRate = 0;
  198. hr = mDevice->getD3D11Device()->CreateInputLayout(declElements, 2, microcode->GetBufferPointer(),
  199. microcode->GetBufferSize(), &mClearQuadIL);
  200. bs_deleteN<ScratchAlloc>(declElements, 2);
  201. if (FAILED(hr))
  202. {
  203. BS_EXCEPT(RenderingAPIException, "Cannot create D3D11 input layout.");
  204. }
  205. // Create vertex buffer
  206. D3D11_BUFFER_DESC mVBDesc;
  207. mVBDesc.ByteWidth = sizeof(ClearVertex) * 4;
  208. mVBDesc.MiscFlags = 0;
  209. mVBDesc.StructureByteStride = 0;
  210. mVBDesc.Usage = D3D11_USAGE_DEFAULT;
  211. mVBDesc.CPUAccessFlags = 0;
  212. mVBDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  213. ClearVertex vertexData[4];
  214. vertexData[0].pos = Vector3(0, 0, 0);
  215. vertexData[1].pos = Vector3(0, 0, 0);
  216. vertexData[2].pos = Vector3(0, 0, 0);
  217. vertexData[3].pos = Vector3(0, 0, 0);
  218. vertexData[0].col = Color::White.getAsBGRA();
  219. vertexData[1].col = Color::White.getAsBGRA();
  220. vertexData[2].col = Color::White.getAsBGRA();
  221. vertexData[3].col = Color::White.getAsBGRA();
  222. D3D11_SUBRESOURCE_DATA vertexSubresourceData;
  223. vertexSubresourceData.pSysMem = vertexData;
  224. hr = mDevice->getD3D11Device()->CreateBuffer(&mVBDesc, &vertexSubresourceData, &mClearQuadVB);
  225. if (FAILED(hr) || mDevice->hasError())
  226. {
  227. String msg = mDevice->getErrorDescription();
  228. BS_EXCEPT(RenderingAPIException, "Cannot create D3D11 buffer: " + msg);
  229. }
  230. // Create index buffer
  231. D3D11_BUFFER_DESC mIBDesc;
  232. mIBDesc.ByteWidth = sizeof(UINT16) * 6;
  233. mIBDesc.MiscFlags = 0;
  234. mIBDesc.StructureByteStride = 0;
  235. mIBDesc.Usage = D3D11_USAGE_DEFAULT;
  236. mIBDesc.CPUAccessFlags = 0;
  237. mIBDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
  238. UINT16 indexData[6];
  239. indexData[0] = 0;
  240. indexData[1] = 1;
  241. indexData[2] = 2;
  242. indexData[3] = 1;
  243. indexData[4] = 3;
  244. indexData[5] = 2;
  245. D3D11_SUBRESOURCE_DATA indexSubresourceData;
  246. indexSubresourceData.pSysMem = indexData;
  247. hr = mDevice->getD3D11Device()->CreateBuffer(&mIBDesc, &indexSubresourceData, &mClearQuadIB);
  248. if (FAILED(hr) || mDevice->hasError())
  249. {
  250. String msg = mDevice->getErrorDescription();
  251. BS_EXCEPT(RenderingAPIException, "Cannot create D3D11 buffer: " + msg);
  252. }
  253. }
  254. }