oculusVRHMDDevice.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/input/oculusVR/oculusVRHMDDevice.h"
  23. #include "platform/input/oculusVR/oculusVRDevice.h"
  24. #include "platform/input/oculusVR/oculusVRSensorDevice.h"
  25. #include "postFx/postEffectCommon.h"
  26. #include "gui/core/guiCanvas.h"
  27. #include "platform/input/oculusVR/oculusVRUtil.h"
  28. #include "core/stream/fileStream.h"
  29. #include "gfx/D3D11/gfxD3D11Device.h"
  30. #include "gfx/D3D11/gfxD3D11EnumTranslate.h"
  31. #include "gfx/gfxStringEnumTranslate.h"
  32. #undef D3D11
  33. // Use D3D11 for win32
  34. #ifdef TORQUE_OS_WIN
  35. #define OVR_D3D_VERSION 11
  36. #include "OVR_CAPI_D3D.h"
  37. #define OCULUS_USE_D3D
  38. #else
  39. #include "OVR_CAPI_GL.h"
  40. #define OCULUS_USE_GL
  41. #endif
  42. struct OculusTexture
  43. {
  44. virtual void AdvanceToNextTexture() = 0;
  45. virtual ~OculusTexture() {
  46. }
  47. };
  48. //------------------------------------------------------------
  49. // ovrSwapTextureSet wrapper class that also maintains the render target views
  50. // needed for D3D11 rendering.
  51. struct D3D11OculusTexture : public OculusTexture
  52. {
  53. ovrHmd hmd;
  54. ovrSwapTextureSet * TextureSet;
  55. static const int TextureCount = 2;
  56. GFXTexHandle TexRtv[TextureCount];
  57. GFXDevice *Owner;
  58. D3D11OculusTexture(GFXDevice* owner) :
  59. hmd(nullptr),
  60. TextureSet(nullptr),
  61. Owner(owner)
  62. {
  63. TexRtv[0] = TexRtv[1] = nullptr;
  64. }
  65. bool Init(ovrHmd _hmd, int sizeW, int sizeH)
  66. {
  67. hmd = _hmd;
  68. D3D11_TEXTURE2D_DESC dsDesc;
  69. dsDesc.Width = sizeW;
  70. dsDesc.Height = sizeH;
  71. dsDesc.MipLevels = 1;
  72. dsDesc.ArraySize = 1;
  73. dsDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;// DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
  74. dsDesc.SampleDesc.Count = 1; // No multi-sampling allowed
  75. dsDesc.SampleDesc.Quality = 0;
  76. dsDesc.Usage = D3D11_USAGE_DEFAULT;
  77. dsDesc.CPUAccessFlags = 0;
  78. dsDesc.MiscFlags = 0;
  79. dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
  80. GFXD3D11Device* device = static_cast<GFXD3D11Device*>(GFX);
  81. ovrResult result = ovr_CreateSwapTextureSetD3D11(hmd, device->mD3DDevice, &dsDesc, ovrSwapTextureSetD3D11_Typeless, &TextureSet);
  82. if (!OVR_SUCCESS(result))
  83. return false;
  84. AssertFatal(TextureSet->TextureCount == TextureCount, "TextureCount mismatch.");
  85. for (int i = 0; i < TextureCount; ++i)
  86. {
  87. ovrD3D11Texture* tex = (ovrD3D11Texture*)&TextureSet->Textures[i];
  88. D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
  89. rtvd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;// DXGI_FORMAT_R8G8B8A8_UNORM;
  90. rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  91. GFXD3D11TextureObject* object = new GFXD3D11TextureObject(GFX, &VRTextureProfile);
  92. object->registerResourceWithDevice(GFX);
  93. *(object->getSRViewPtr()) = tex->D3D11.pSRView;
  94. *(object->get2DTexPtr()) = tex->D3D11.pTexture;
  95. device->mD3DDevice->CreateRenderTargetView(tex->D3D11.pTexture, &rtvd, object->getRTViewPtr());
  96. // Add refs for texture release later on
  97. if (object->getSRView()) object->getSRView()->AddRef();
  98. //object->getRTView()->AddRef();
  99. if (object->get2DTex()) object->get2DTex()->AddRef();
  100. object->isManaged = true;
  101. // Get the actual size of the texture...
  102. D3D11_TEXTURE2D_DESC probeDesc;
  103. ZeroMemory(&probeDesc, sizeof(D3D11_TEXTURE2D_DESC));
  104. object->get2DTex()->GetDesc(&probeDesc);
  105. object->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0);
  106. object->mBitmapSize = object->mTextureSize;
  107. int fmt = probeDesc.Format;
  108. if (fmt == DXGI_FORMAT_R8G8B8A8_TYPELESS || fmt == DXGI_FORMAT_B8G8R8A8_TYPELESS)
  109. {
  110. object->mFormat = GFXFormatR8G8B8A8; // usual case
  111. }
  112. else
  113. {
  114. // TODO: improve this. this can be very bad.
  115. GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, fmt);
  116. object->mFormat = (GFXFormat)fmt;
  117. }
  118. TexRtv[i] = object;
  119. }
  120. return true;
  121. }
  122. ~D3D11OculusTexture()
  123. {
  124. for (int i = 0; i < TextureCount; ++i)
  125. {
  126. SAFE_DELETE(TexRtv[i]);
  127. }
  128. if (TextureSet)
  129. {
  130. ovr_DestroySwapTextureSet(hmd, TextureSet);
  131. }
  132. }
  133. void AdvanceToNextTexture()
  134. {
  135. TextureSet->CurrentIndex = (TextureSet->CurrentIndex + 1) % TextureSet->TextureCount;
  136. }
  137. };
  138. OculusVRHMDDevice::OculusVRHMDDevice()
  139. {
  140. mIsValid = false;
  141. mDevice = NULL;
  142. mCurrentCaps = 0;
  143. mSupportedCaps = 0;
  144. mVsync = true;
  145. mTimewarp = true;
  146. mRenderConfigurationDirty = true;
  147. mCurrentPixelDensity = OculusVRDevice::smDesiredPixelDensity;
  148. mDesiredRenderingMode = GFXDevice::RS_StereoSideBySide;
  149. mRTFormat = GFXFormatR8G8B8A8;
  150. mDrawCanvas = NULL;
  151. mFrameReady = false;
  152. mConnection = NULL;
  153. mSensor = NULL;
  154. mActionCodeIndex = 0;
  155. mTextureSwapSet = NULL;
  156. }
  157. OculusVRHMDDevice::~OculusVRHMDDevice()
  158. {
  159. cleanUp();
  160. }
  161. void OculusVRHMDDevice::cleanUp()
  162. {
  163. onDeviceDestroy();
  164. if (mSensor)
  165. {
  166. delete mSensor;
  167. mSensor = NULL;
  168. }
  169. if(mDevice)
  170. {
  171. ovr_Destroy(mDevice);
  172. mDevice = NULL;
  173. }
  174. mIsValid = false;
  175. }
  176. void OculusVRHMDDevice::set(ovrHmd hmd, ovrGraphicsLuid luid, U32 actionCodeIndex)
  177. {
  178. cleanUp();
  179. mIsValid = false;
  180. mRenderConfigurationDirty = true;
  181. mDevice = hmd;
  182. ovrHmdDesc desc = ovr_GetHmdDesc(hmd);
  183. int caps = ovr_GetTrackingCaps(hmd);
  184. mSupportedCaps = desc.AvailableHmdCaps;
  185. mCurrentCaps = mSupportedCaps;
  186. mTimewarp = true;
  187. // DeviceInfo
  188. mProductName = desc.ProductName;
  189. mManufacturer = desc.Manufacturer;
  190. mVersion = desc.FirmwareMajor;
  191. //
  192. Vector<GFXAdapter*> adapterList;
  193. GFXD3D11Device::enumerateAdapters(adapterList);
  194. dMemcpy(&mLuid, &luid, sizeof(mLuid));
  195. mDisplayId = -1;
  196. for (U32 i = 0, sz = adapterList.size(); i < sz; i++)
  197. {
  198. GFXAdapter* adapter = adapterList[i];
  199. if (dMemcmp(&adapter->mLUID, &mLuid, sizeof(mLuid)) == 0)
  200. {
  201. mDisplayId = adapter->mIndex;
  202. mDisplayDeviceType = "D3D11"; // TOFIX this
  203. }
  204. }
  205. mResolution.x = desc.Resolution.w;
  206. mResolution.y = desc.Resolution.h;
  207. mProfileInterpupillaryDistance = ovr_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD);
  208. mLensSeparation = ovr_GetFloat(hmd, "LensSeparation", 0);
  209. ovr_GetFloatArray(hmd, "ScreenSize", &mScreenSize.x, 2);
  210. mActionCodeIndex = actionCodeIndex;
  211. mIsValid = true;
  212. mSensor = new OculusVRSensorDevice();
  213. mSensor->set(mDevice, mActionCodeIndex);
  214. mDebugMirrorTexture = NULL;
  215. updateCaps();
  216. }
  217. void OculusVRHMDDevice::setIPD(F32 ipd)
  218. {
  219. mInterpupillaryDistance = ipd;
  220. }
  221. void OculusVRHMDDevice::setOptimalDisplaySize(GuiCanvas *canvas)
  222. {
  223. if (!mDevice)
  224. return;
  225. PlatformWindow *window = canvas->getPlatformWindow();
  226. GFXTarget *target = window->getGFXTarget();
  227. Point2I requiredSize(0, 0);
  228. ovrHmdDesc desc = ovr_GetHmdDesc(mDevice);
  229. ovrSizei leftSize = ovr_GetFovTextureSize(mDevice, ovrEye_Left, desc.DefaultEyeFov[0], mCurrentPixelDensity);
  230. ovrSizei rightSize = ovr_GetFovTextureSize(mDevice, ovrEye_Right, desc.DefaultEyeFov[1], mCurrentPixelDensity);
  231. requiredSize.x = leftSize.w + rightSize.h;
  232. requiredSize.y = mMax(leftSize.h, rightSize.h);
  233. if (target && target->getSize() != requiredSize)
  234. {
  235. GFXVideoMode newMode;
  236. newMode.antialiasLevel = 0;
  237. newMode.bitDepth = 32;
  238. newMode.fullScreen = false;
  239. newMode.refreshRate = 75;
  240. newMode.resolution = requiredSize;
  241. newMode.wideScreen = false;
  242. window->setVideoMode(newMode);
  243. //AssertFatal(window->getClientExtent().x == requiredSize.x && window->getClientExtent().y == requiredSize.y, "Window didn't resize to correct dimensions");
  244. }
  245. }
  246. bool OculusVRHMDDevice::isDisplayingWarning()
  247. {
  248. if (!mIsValid || !mDevice)
  249. return false;
  250. return false;/*
  251. ovrHSWDisplayState displayState;
  252. ovrHmd_GetHSWDisplayState(mDevice, &displayState);
  253. return displayState.Displayed;*/
  254. }
  255. void OculusVRHMDDevice::dismissWarning()
  256. {
  257. if (!mIsValid || !mDevice)
  258. return;
  259. //ovr_DismissHSWDisplay(mDevice);
  260. }
  261. GFXTexHandle OculusVRHMDDevice::getPreviewTexture()
  262. {
  263. if (!mIsValid || !mDevice)
  264. return NULL;
  265. return mDebugMirrorTextureHandle;
  266. }
  267. bool OculusVRHMDDevice::setupTargets()
  268. {
  269. // Create eye render buffers
  270. ID3D11RenderTargetView * eyeRenderTexRtv[2];
  271. ovrLayerEyeFov ld = { { ovrLayerType_EyeFov } };
  272. mRenderLayer = ld;
  273. GFXD3D11Device* device = static_cast<GFXD3D11Device*>(GFX);
  274. ovrHmdDesc desc = ovr_GetHmdDesc(mDevice);
  275. for (int i = 0; i < 2; i++)
  276. {
  277. mRenderLayer.Fov[i] = desc.DefaultEyeFov[i];
  278. mRenderLayer.Viewport[i].Size = ovr_GetFovTextureSize(mDevice, (ovrEyeType)i, mRenderLayer.Fov[i], mCurrentPixelDensity);
  279. mEyeRenderDesc[i] = ovr_GetRenderDesc(mDevice, (ovrEyeType_)(ovrEye_Left+i), mRenderLayer.Fov[i]);
  280. }
  281. ovrSizei recommendedEyeTargetSize[2];
  282. recommendedEyeTargetSize[0] = mRenderLayer.Viewport[0].Size;
  283. recommendedEyeTargetSize[1] = mRenderLayer.Viewport[1].Size;
  284. if (mTextureSwapSet)
  285. {
  286. delete mTextureSwapSet;
  287. mTextureSwapSet = NULL;
  288. }
  289. // Calculate render target size
  290. if (mDesiredRenderingMode == GFXDevice::RS_StereoSideBySide)
  291. {
  292. // Setup a single texture, side-by-side viewports
  293. Point2I rtSize(
  294. recommendedEyeTargetSize[0].w + recommendedEyeTargetSize[1].w,
  295. recommendedEyeTargetSize[0].h > recommendedEyeTargetSize[1].h ? recommendedEyeTargetSize[0].h : recommendedEyeTargetSize[1].h
  296. );
  297. GFXFormat targetFormat = GFX->getActiveRenderTarget()->getFormat();
  298. mRTFormat = targetFormat;
  299. rtSize = generateRenderTarget(mStereoRT, mStereoDepthTexture, rtSize);
  300. // Generate the swap texture we need to store the final image
  301. D3D11OculusTexture* tex = new D3D11OculusTexture(GFX);
  302. if (tex->Init(mDevice, rtSize.x, rtSize.y))
  303. {
  304. mTextureSwapSet = tex;
  305. }
  306. mRenderLayer.ColorTexture[0] = tex->TextureSet;
  307. mRenderLayer.ColorTexture[1] = tex->TextureSet;
  308. mRenderLayer.Viewport[0].Pos.x = 0;
  309. mRenderLayer.Viewport[0].Pos.y = 0;
  310. mRenderLayer.Viewport[1].Pos.x = (rtSize.x + 1) / 2;
  311. mRenderLayer.Viewport[1].Pos.y = 0;
  312. // Left
  313. mEyeRT[0] = mStereoRT;
  314. mEyeViewport[0] = RectI(Point2I(mRenderLayer.Viewport[0].Pos.x, mRenderLayer.Viewport[0].Pos.y), Point2I(mRenderLayer.Viewport[0].Size.w, mRenderLayer.Viewport[0].Size.h));
  315. // Right
  316. mEyeRT[1] = mStereoRT;
  317. mEyeViewport[1] = RectI(Point2I(mRenderLayer.Viewport[1].Pos.x, mRenderLayer.Viewport[1].Pos.y), Point2I(mRenderLayer.Viewport[1].Size.w, mRenderLayer.Viewport[1].Size.h));
  318. GFXD3D11Device* device = static_cast<GFXD3D11Device*>(GFX);
  319. D3D11_TEXTURE2D_DESC dsDesc;
  320. dsDesc.Width = rtSize.x;
  321. dsDesc.Height = rtSize.y;
  322. dsDesc.MipLevels = 1;
  323. dsDesc.ArraySize = 1;
  324. dsDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;// DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
  325. dsDesc.SampleDesc.Count = 1;
  326. dsDesc.SampleDesc.Quality = 0;
  327. dsDesc.Usage = D3D11_USAGE_DEFAULT;
  328. dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  329. dsDesc.CPUAccessFlags = 0;
  330. dsDesc.MiscFlags = 0;
  331. // Create typeless when we are rendering as non-sRGB since we will override the texture format in the RTV
  332. bool reinterpretSrgbAsLinear = true;
  333. unsigned compositorTextureFlags = 0;
  334. if (reinterpretSrgbAsLinear)
  335. compositorTextureFlags |= ovrSwapTextureSetD3D11_Typeless;
  336. ovrResult result = ovr_CreateMirrorTextureD3D11(mDevice, device->mD3DDevice, &dsDesc, compositorTextureFlags, &mDebugMirrorTexture);
  337. if (result == ovrError_DisplayLost || !mDebugMirrorTexture)
  338. {
  339. AssertFatal(false, "Something went wrong");
  340. return NULL;
  341. }
  342. // Create texture handle so we can render it in-game
  343. ovrD3D11Texture* mirror_tex = (ovrD3D11Texture*)mDebugMirrorTexture;
  344. D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
  345. rtvd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;// DXGI_FORMAT_R8G8B8A8_UNORM;
  346. rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  347. GFXD3D11TextureObject* object = new GFXD3D11TextureObject(GFX, &VRTextureProfile);
  348. object->registerResourceWithDevice(GFX);
  349. *(object->getSRViewPtr()) = mirror_tex->D3D11.pSRView;
  350. *(object->get2DTexPtr()) = mirror_tex->D3D11.pTexture;
  351. device->mD3DDevice->CreateRenderTargetView(mirror_tex->D3D11.pTexture, &rtvd, object->getRTViewPtr());
  352. // Add refs for texture release later on
  353. if (object->getSRView()) object->getSRView()->AddRef();
  354. //object->getRTView()->AddRef();
  355. if (object->get2DTex()) object->get2DTex()->AddRef();
  356. object->isManaged = true;
  357. // Get the actual size of the texture...
  358. D3D11_TEXTURE2D_DESC probeDesc;
  359. ZeroMemory(&probeDesc, sizeof(D3D11_TEXTURE2D_DESC));
  360. object->get2DTex()->GetDesc(&probeDesc);
  361. object->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0);
  362. object->mBitmapSize = object->mTextureSize;
  363. int fmt = probeDesc.Format;
  364. if (fmt == DXGI_FORMAT_R8G8B8A8_TYPELESS || fmt == DXGI_FORMAT_B8G8R8A8_TYPELESS)
  365. {
  366. object->mFormat = GFXFormatR8G8B8A8; // usual case
  367. }
  368. else
  369. {
  370. // TODO: improve this. this can be very bad.
  371. GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, fmt);
  372. object->mFormat = (GFXFormat)fmt;
  373. }
  374. mDebugMirrorTextureHandle = object;
  375. }
  376. else
  377. {
  378. // No rendering, abort!
  379. return false;
  380. }
  381. return true;
  382. }
  383. String OculusVRHMDDevice::dumpMetrics()
  384. {
  385. StringBuilder sb;
  386. EulerF rot = mSensor->getEulerRotation();
  387. Point3F pos = mSensor->getPosition();
  388. FovPort eyeFov[2];
  389. this->getFovPorts(eyeFov);
  390. mSensor->getPositionTrackingAvailable();
  391. F32 ipd = this->getIPD();
  392. U32 lastStatus = mSensor->getLastTrackingStatus();
  393. sb.format(" | OVR Sensor %i | rot: %f %f %f, pos: %f %f %f, FOV (%f %f %f %f, %f %f %f %f), IPD %f, Track:%s%s",
  394. mActionCodeIndex,
  395. rot.x, rot.y, rot.z,
  396. pos.x, pos.y, pos.z,
  397. eyeFov[0].upTan, eyeFov[0].downTan, eyeFov[0].leftTan, eyeFov[0].rightTan, eyeFov[1].upTan, eyeFov[1].downTan, eyeFov[1].leftTan, eyeFov[1].rightTan,
  398. getIPD(),
  399. lastStatus & ovrStatus_OrientationTracked ? " ORIENT" : "",
  400. lastStatus & ovrStatus_PositionTracked ? " POS" : "");
  401. return sb.data();
  402. }
  403. void OculusVRHMDDevice::updateRenderInfo()
  404. {
  405. // Check console values first
  406. if (mCurrentPixelDensity != OculusVRDevice::smDesiredPixelDensity)
  407. {
  408. mRenderConfigurationDirty = true;
  409. mCurrentPixelDensity = OculusVRDevice::smDesiredPixelDensity;
  410. }
  411. if (!mIsValid || !mDevice || !mRenderConfigurationDirty)
  412. return;
  413. if (!mDrawCanvas)
  414. return;
  415. PlatformWindow *window = mDrawCanvas->getPlatformWindow();
  416. ovrHmdDesc desc = ovr_GetHmdDesc(mDevice);
  417. // Update window size if it's incorrect
  418. Point2I backbufferSize = mDrawCanvas->getBounds().extent;
  419. // Finally setup!
  420. if (!setupTargets())
  421. {
  422. onDeviceDestroy();
  423. return;
  424. }
  425. mRenderConfigurationDirty = false;
  426. }
  427. Point2I OculusVRHMDDevice::generateRenderTarget(GFXTextureTargetRef &target, GFXTexHandle &depth, Point2I desiredSize)
  428. {
  429. // Texture size that we already have might be big enough.
  430. Point2I newRTSize;
  431. bool newRT = false;
  432. if (!target.getPointer())
  433. {
  434. target = GFX->allocRenderToTextureTarget();
  435. newRTSize = desiredSize;
  436. newRT = true;
  437. }
  438. else
  439. {
  440. Point2I currentSize = target->getSize();
  441. newRTSize = currentSize;
  442. }
  443. // %50 linear growth each time is a nice balance between being too greedy
  444. // for a 2D surface and too slow to prevent fragmentation.
  445. while ( newRTSize.x < desiredSize.x )
  446. {
  447. newRTSize.x += newRTSize.x/2;
  448. }
  449. while ( newRTSize.y < desiredSize.y )
  450. {
  451. newRTSize.y += newRTSize.y/2;
  452. }
  453. // Put some sane limits on it. 4k x 4k is fine for most modern video cards.
  454. // Nobody should be messing around with surfaces smaller than 4k pixels these days.
  455. newRTSize.setMin(Point2I(4096, 4096));
  456. newRTSize.setMax(Point2I(64, 64));
  457. // Stereo RT needs to be the same size as the recommended RT
  458. /*if ( newRT || mDebugStereoTexture.getWidthHeight() != newRTSize )
  459. {
  460. mDebugStereoTexture.set( newRTSize.x, newRTSize.y, mRTFormat, &VRTextureProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) );
  461. target->attachTexture( GFXTextureTarget::Color0, mDebugStereoTexture);
  462. Con::printf("generateRenderTarget generated %x", mDebugStereoTexture.getPointer());
  463. }*/
  464. if ( depth.getWidthHeight() != newRTSize )
  465. {
  466. depth.set( newRTSize.x, newRTSize.y, GFXFormatD24S8, &VRDepthProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) );
  467. target->attachTexture( GFXTextureTarget::DepthStencil, depth );
  468. Con::printf("generateRenderTarget generated depth %x", depth.getPointer());
  469. }
  470. return newRTSize;
  471. }
  472. void OculusVRHMDDevice::clearRenderTargets()
  473. {
  474. mStereoRT = NULL;
  475. mEyeRT[0] = NULL;
  476. mEyeRT[1] = NULL;
  477. if (mDebugMirrorTexture)
  478. {
  479. ovr_DestroyMirrorTexture(mDevice, mDebugMirrorTexture);
  480. mDebugMirrorTexture = NULL;
  481. mDebugMirrorTextureHandle = NULL;
  482. }
  483. }
  484. void OculusVRHMDDevice::updateCaps()
  485. {
  486. if (!mIsValid || !mDevice)
  487. return;
  488. ovr_SetEnabledCaps(mDevice, mCurrentCaps);
  489. }
  490. static bool sInFrame = false; // protects against recursive onStartFrame calls
  491. void OculusVRHMDDevice::onStartFrame()
  492. {
  493. if (!mIsValid || !mDevice || !mDrawCanvas || sInFrame || mFrameReady)
  494. return;
  495. sInFrame = true;
  496. ovrVector3f hmdToEyeViewOffset[2] = { mEyeRenderDesc[0].HmdToEyeViewOffset, mEyeRenderDesc[1].HmdToEyeViewOffset };
  497. ovrTrackingState hmdState = ovr_GetTrackingState(mDevice, 0, ovrTrue);
  498. ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewOffset, mRenderLayer.RenderPose);
  499. for (U32 i=0; i<2; i++)
  500. {
  501. mRenderLayer.RenderPose[i].Position.x *= OculusVRDevice::smPositionTrackingScale;
  502. mRenderLayer.RenderPose[i].Position.y *= OculusVRDevice::smPositionTrackingScale;
  503. mRenderLayer.RenderPose[i].Position.z *= OculusVRDevice::smPositionTrackingScale;
  504. }
  505. mRenderLayer.SensorSampleTime = ovr_GetTimeInSeconds();
  506. // Set current dest texture on stereo render target
  507. D3D11OculusTexture* texSwap = (D3D11OculusTexture*)mTextureSwapSet;
  508. mStereoRT->attachTexture(GFXTextureTarget::Color0, texSwap->TexRtv[texSwap->TextureSet->CurrentIndex]);
  509. sInFrame = false;
  510. mFrameReady = true;
  511. }
  512. void OculusVRHMDDevice::onEndFrame()
  513. {
  514. if (!mIsValid || !mDevice || !mDrawCanvas || sInFrame || !mFrameReady || !mTextureSwapSet)
  515. return;
  516. Point2I eyeSize;
  517. GFXTarget *windowTarget = mDrawCanvas->getPlatformWindow()->getGFXTarget();
  518. GFXD3D11Device *d3d11GFX = dynamic_cast<GFXD3D11Device*>(GFX);
  519. ovrViewScaleDesc viewScaleDesc;
  520. ovrVector3f hmdToEyeViewOffset[2] = { mEyeRenderDesc[0].HmdToEyeViewOffset, mEyeRenderDesc[1].HmdToEyeViewOffset };
  521. viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
  522. viewScaleDesc.HmdToEyeViewOffset[0] = hmdToEyeViewOffset[0];
  523. viewScaleDesc.HmdToEyeViewOffset[1] = hmdToEyeViewOffset[1];
  524. ovrLayerDirect ld = { { ovrLayerType_Direct } };
  525. mDebugRenderLayer = ld;
  526. mDebugRenderLayer.ColorTexture[0] = mRenderLayer.ColorTexture[0];
  527. mDebugRenderLayer.ColorTexture[1] = mRenderLayer.ColorTexture[1];
  528. mDebugRenderLayer.Viewport[0] = mRenderLayer.Viewport[0];
  529. mDebugRenderLayer.Viewport[1] = mRenderLayer.Viewport[1];
  530. // TODO: use ovrViewScaleDesc
  531. ovrLayerHeader* layers = &mRenderLayer.Header;
  532. ovrResult result = ovr_SubmitFrame(mDevice, 0, &viewScaleDesc, &layers, 1);
  533. mTextureSwapSet->AdvanceToNextTexture();
  534. if (OVR_SUCCESS(result))
  535. {
  536. int woo = 1;
  537. }
  538. // TODO: render preview in display?
  539. mFrameReady = false;
  540. }
  541. void OculusVRHMDDevice::getFrameEyePose(DisplayPose *outPose, U32 eyeId) const
  542. {
  543. // Directly set the rotation and position from the eye transforms
  544. ovrPosef pose = mRenderLayer.RenderPose[eyeId];
  545. OVR::Quatf orientation = pose.Orientation;
  546. const OVR::Vector3f position = pose.Position;
  547. MatrixF torqueMat(1);
  548. OVR::Matrix4f mat(orientation);
  549. OculusVRUtil::convertRotation(mat.M, torqueMat);
  550. outPose->orientation = QuatF(torqueMat);
  551. outPose->position = Point3F(-position.x, position.z, -position.y);
  552. }
  553. void OculusVRHMDDevice::onDeviceDestroy()
  554. {
  555. if (!mIsValid || !mDevice)
  556. return;
  557. if (mStereoRT.getPointer())
  558. {
  559. mStereoRT->zombify();
  560. }
  561. if (mEyeRT[1].getPointer() && mEyeRT[1] != mStereoRT)
  562. {
  563. mEyeRT[0]->zombify();
  564. mEyeRT[1]->zombify();
  565. }
  566. if (mTextureSwapSet)
  567. {
  568. delete mTextureSwapSet;
  569. mTextureSwapSet = NULL;
  570. }
  571. mStereoRT = NULL;
  572. mStereoDepthTexture = NULL;
  573. mEyeRT[0] = NULL;
  574. mEyeRT[1] = NULL;
  575. mRenderConfigurationDirty = true;
  576. }