Util_D3D11_Blitter.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /************************************************************************************
  2. Filename : Util_D3D11_Blitter.cpp
  3. Content : D3D11 implementation for blitting, supporting scaling & rotation
  4. Created : February 24, 2015
  5. Authors : Reza Nourai
  6. Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
  7. Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  8. you may not use the Oculus VR Rift SDK except in compliance with the License,
  9. which is provided at the time of installation or download, or which
  10. otherwise accompanies this software in either electronic or hard copy form.
  11. You may obtain a copy of the License at
  12. http://www.oculusvr.com/licenses/LICENSE-3.2
  13. Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  14. distributed under the License is distributed on an "AS IS" BASIS,
  15. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. See the License for the specific language governing permissions and
  17. limitations under the License.
  18. ************************************************************************************/
  19. #include "Util_D3D11_Blitter.h"
  20. #ifdef OVR_OS_MS
  21. #include "Util/Util_Direct3D.h"
  22. #include "Shaders/Blt_vs.h"
  23. #include "Shaders/Blt_ps.h"
  24. namespace OVR { namespace D3DUtil {
  25. //-------------------------------------------------------------------------------------
  26. // ***** CAPI::Blitter
  27. Blitter::Blitter(const Ptr<ID3D11Device>& device) :
  28. Device(),
  29. Context1(),
  30. BltState(),
  31. IL(),
  32. VB(),
  33. VS(),
  34. PS(),
  35. Sampler(),
  36. AlreadyInitialized(false)
  37. {
  38. device->QueryInterface(IID_PPV_ARGS(&Device.GetRawRef()));
  39. OVR_ASSERT(Device);
  40. Device->GetImmediateContext1(&Context1.GetRawRef());
  41. OVR_ASSERT(Context1);
  42. }
  43. Blitter::~Blitter()
  44. {
  45. }
  46. bool Blitter::Initialize()
  47. {
  48. if (!Device)
  49. {
  50. OVR_ASSERT(false);
  51. return false;
  52. }
  53. OVR_ASSERT(!AlreadyInitialized);
  54. if (AlreadyInitialized)
  55. {
  56. return false;
  57. }
  58. UINT deviceFlags = Device->GetCreationFlags();
  59. D3D_FEATURE_LEVEL featureLevel = Device->GetFeatureLevel();
  60. // If the device is single threaded, the context state must be too
  61. UINT stateFlags = 0;
  62. if (deviceFlags & D3D11_CREATE_DEVICE_SINGLETHREADED)
  63. {
  64. stateFlags |= D3D11_1_CREATE_DEVICE_CONTEXT_STATE_SINGLETHREADED;
  65. }
  66. // TODO: Clean this up with OVR_D3D_CREATE() when we move OVRError to kernel.
  67. OVR_ASSERT(!BltState); // Expected to be null on the way in.
  68. BltState = nullptr; // Prevents a potential leak on the next line.
  69. HRESULT hr = Device->CreateDeviceContextState(stateFlags, &featureLevel, 1, D3D11_SDK_VERSION, __uuidof(ID3D11Device1), nullptr, &BltState.GetRawRef());
  70. OVR_D3D_CHECK_RET_FALSE(hr);
  71. OVR_D3D_TAG_OBJECT(BltState);
  72. OVR_ASSERT(!VS); // Expected to be null on the way in.
  73. VS = nullptr; // Prevents a potential leak on the next line.
  74. hr = Device->CreateVertexShader(Blt_vs, sizeof(Blt_vs), nullptr, &VS.GetRawRef());
  75. OVR_D3D_CHECK_RET_FALSE(hr);
  76. OVR_D3D_TAG_OBJECT(VS);
  77. OVR_ASSERT(!PS); // Expected to be null on the way in.
  78. PS = nullptr; // Prevents a potential leak on the next line.
  79. hr = Device->CreatePixelShader(Blt_ps, sizeof(Blt_ps), nullptr, &PS.GetRawRef());
  80. OVR_D3D_CHECK_RET_FALSE(hr);
  81. OVR_D3D_TAG_OBJECT(PS);
  82. D3D11_INPUT_ELEMENT_DESC elems[2] = {};
  83. elems[0].Format = DXGI_FORMAT_R32G32_FLOAT;
  84. elems[0].SemanticName = "POSITION";
  85. elems[1].AlignedByteOffset = sizeof(float)* 2;
  86. elems[1].Format = DXGI_FORMAT_R32G32_FLOAT;
  87. elems[1].SemanticName = "TEXCOORD";
  88. OVR_ASSERT(!IL); // Expected to be null on the way in.
  89. IL = nullptr; // Prevents a potential leak on the next line.
  90. hr = Device->CreateInputLayout(elems, _countof(elems), Blt_vs, sizeof(Blt_vs), &IL.GetRawRef());
  91. OVR_D3D_CHECK_RET_FALSE(hr);
  92. OVR_D3D_TAG_OBJECT(IL);
  93. // Quad with texcoords designed to rotate the source 90deg clockwise
  94. BltVertex vertices[] =
  95. {
  96. { -1, 1, 0, 0 },
  97. { 1, 1, 1, 0 },
  98. { 1, -1, 1, 1 },
  99. { -1, 1, 0, 0 },
  100. { 1, -1, 1, 1 },
  101. { -1, -1, 0, 1 }
  102. };
  103. D3D11_BUFFER_DESC bd = {};
  104. bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  105. bd.ByteWidth = sizeof(vertices);
  106. bd.StructureByteStride = sizeof(BltVertex);
  107. bd.Usage = D3D11_USAGE_DEFAULT;
  108. D3D11_SUBRESOURCE_DATA init = {};
  109. init.pSysMem = vertices;
  110. init.SysMemPitch = sizeof(vertices);
  111. init.SysMemSlicePitch = init.SysMemPitch;
  112. OVR_ASSERT(!VB); // Expected to be null on the way in.
  113. VB = nullptr; // Prevents a potential leak on the next line.
  114. hr = Device->CreateBuffer(&bd, &init, &VB.GetRawRef());
  115. OVR_D3D_CHECK_RET_FALSE(hr);
  116. OVR_D3D_TAG_OBJECT(VB);
  117. D3D11_SAMPLER_DESC ss = {};
  118. ss.AddressU = ss.AddressV = ss.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
  119. ss.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  120. ss.MaxLOD = 15;
  121. OVR_ASSERT(!Sampler); // Expected to be null on the way in.
  122. Sampler = nullptr; // Prevents a potential leak on the next line.
  123. hr = Device->CreateSamplerState(&ss, &Sampler.GetRawRef());
  124. OVR_D3D_CHECK_RET_FALSE(hr);
  125. // OVR_D3D_TAG_OBJECT(); Seems to already have a name.
  126. // Swap to our blt state to set it up
  127. Ptr<ID3DDeviceContextState> existingState;
  128. Context1->SwapDeviceContextState(BltState, &existingState.GetRawRef());
  129. Context1->IASetInputLayout(IL);
  130. Context1->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  131. Context1->VSSetShader(VS, nullptr, 0);
  132. Context1->PSSetShader(PS, nullptr, 0);
  133. Context1->PSSetSamplers(0, 1, &Sampler.GetRawRef());
  134. // Swap back
  135. Context1->SwapDeviceContextState(existingState, nullptr);
  136. AlreadyInitialized = true;
  137. return true;
  138. }
  139. bool Blitter::Blt(ID3D11RenderTargetView* dest, ID3D11ShaderResourceView* source)
  140. {
  141. OVR_ASSERT(AlreadyInitialized);
  142. if (!AlreadyInitialized)
  143. {
  144. return false;
  145. }
  146. // Switch to our state
  147. Ptr<ID3DDeviceContextState> existingState;
  148. Context1->SwapDeviceContextState(BltState, &existingState.GetRawRef());
  149. ID3D11RenderTargetView* nullRTVs[] = { nullptr, nullptr, nullptr, nullptr };
  150. ID3D11ShaderResourceView* nullSRVs[] = { nullptr, nullptr, nullptr, nullptr };
  151. Context1->OMSetRenderTargets(_countof(nullRTVs), nullRTVs, nullptr);
  152. Context1->PSSetShaderResources(0, _countof(nullSRVs), nullSRVs);
  153. // Set the mirror as the render target
  154. Context1->OMSetRenderTargets(1, &dest, nullptr);
  155. Ptr<ID3D11Resource> resource;
  156. dest->GetResource(&resource.GetRawRef());
  157. Ptr<ID3D11Texture2D> texture;
  158. HRESULT hr = resource->QueryInterface(IID_PPV_ARGS(&texture.GetRawRef()));
  159. OVR_D3D_CHECK_RET_FALSE(hr);
  160. D3D11_TEXTURE2D_DESC desc = {};
  161. texture->GetDesc(&desc);
  162. D3D11_VIEWPORT vp = {};
  163. vp.Width = (float)desc.Width;
  164. vp.Height = (float)desc.Height;
  165. vp.MaxDepth = 1.0f;
  166. Context1->RSSetViewports(1, &vp);
  167. Context1->PSSetShaderResources(0, 1, &source);
  168. static const uint32_t stride = sizeof(BltVertex);
  169. static const uint32_t offset = 0;
  170. Context1->IASetVertexBuffers(0, 1, &VB.GetRawRef(), &stride, &offset);
  171. Context1->Draw(6, 0);
  172. Context1->OMSetRenderTargets(_countof(nullRTVs), nullRTVs, nullptr);
  173. Context1->PSSetShaderResources(0, _countof(nullSRVs), nullSRVs);
  174. // Switch back to app state
  175. Context1->SwapDeviceContextState(existingState, nullptr);
  176. return true;
  177. }
  178. }} // namespace OVR::D3DUtil
  179. #endif // OVR_OS_MS