diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp index 3f7cd44f8..49a3835af 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.cpp @@ -128,6 +128,9 @@ void GFXD3D11Device::enumerateAdapters(Vector &adapterList) DXGI_ADAPTER_DESC1 desc; EnumAdapter->GetDesc1(&desc); + // LUID identifies adapter for oculus rift + dMemcpy(&toAdd->mLUID, &desc.AdapterLuid, sizeof(toAdd->mLUID)); + size_t size=wcslen(desc.Description); char *str = new char[size+1]; diff --git a/Engine/source/gfx/D3D11/gfxD3D11Device.h b/Engine/source/gfx/D3D11/gfxD3D11Device.h index 97418d373..8640c8b68 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Device.h +++ b/Engine/source/gfx/D3D11/gfxD3D11Device.h @@ -42,6 +42,8 @@ class PlatformWindow; class GFXD3D11ShaderConstBuffer; +class OculusVRHMDDevice; +class D3D11OculusTexture; //------------------------------------------------------------------------------ @@ -53,6 +55,8 @@ class GFXD3D11Device : public GFXDevice friend class GFXD3D11TextureObject; friend class GFXD3D11TextureTarget; friend class GFXD3D11WindowTarget; + friend class OculusVRHMDDevice; + friend class D3D11OculusTexture; virtual GFXFormat selectSupportedFormat(GFXTextureProfile *profile, const Vector &formats, bool texture, bool mustblend, bool mustfilter); diff --git a/Engine/source/gfx/D3D11/gfxD3D11Target.cpp b/Engine/source/gfx/D3D11/gfxD3D11Target.cpp index a74b3e54d..9c21fa4d3 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11Target.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11Target.cpp @@ -163,6 +163,13 @@ void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *te mTargetSize = Point2I(sd.Width, sd.Height); S32 format = sd.Format; + + if (format == DXGI_FORMAT_R8G8B8A8_TYPELESS || format == DXGI_FORMAT_B8G8R8A8_TYPELESS) + { + mTargetFormat = GFXFormatR8G8B8A8; + return; + } + GFXREVERSE_LOOKUP( GFXD3D11TextureFormat, GFXFormat, format ); mTargetFormat = (GFXFormat)format; } diff --git a/Engine/source/gfx/D3D11/gfxD3D11TextureObject.cpp b/Engine/source/gfx/D3D11/gfxD3D11TextureObject.cpp index 8f15cf550..1c97597cc 100644 --- a/Engine/source/gfx/D3D11/gfxD3D11TextureObject.cpp +++ b/Engine/source/gfx/D3D11/gfxD3D11TextureObject.cpp @@ -67,6 +67,12 @@ GFXLockedRect *GFXD3D11TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect / D3D11_MAPPED_SUBRESOURCE mapInfo; + /*if (!mProfile->canModify()) + { + AssertFatal(false, "Tried to modify external texture"); + return NULL; + }*/ + if( mProfile->isRenderTarget() ) { //AssertFatal( 0, "GFXD3D11TextureObject::lock - Need to handle mapping render targets" ); diff --git a/Engine/source/gfx/gfxAdapter.h b/Engine/source/gfx/gfxAdapter.h index eccf1d7dc..221cc4ef3 100644 --- a/Engine/source/gfx/gfxAdapter.h +++ b/Engine/source/gfx/gfxAdapter.h @@ -35,6 +35,12 @@ #include "core/util/delegate.h" #endif +struct GFXAdapterLUID +{ + unsigned long LowPart; + long HighPart; +}; + struct GFXAdapter { public: @@ -58,6 +64,9 @@ public: /// Supported shader model. 0.f means none supported. F32 mShaderModel; + /// LUID for windows oculus support + GFXAdapterLUID mLUID; + const char * getName() const { return mName; } const char * getOutputName() const { return mOutputName; } GFXAdapterType mType; @@ -72,6 +81,7 @@ public: mOutputName[0] = 0; mShaderModel = 0.f; mIndex = 0; + dMemset(&mLUID, '\0', sizeof(mLUID)); } ~GFXAdapter() diff --git a/Engine/source/gfx/gfxInit.cpp b/Engine/source/gfx/gfxInit.cpp index 09d503d10..bb5e560ac 100644 --- a/Engine/source/gfx/gfxInit.cpp +++ b/Engine/source/gfx/gfxInit.cpp @@ -198,6 +198,22 @@ GFXAdapter* GFXInit::getAdapterOfType( GFXAdapterType type, const char* outputDe return NULL; } +GFXAdapter* GFXInit::getAdapterOfType(GFXAdapterType type, S32 outputDeviceIndex) +{ + for (U32 i = 0; i < smAdapters.size(); i++) + { + if (smAdapters[i]->mType == type) + { + if (smAdapters[i]->mIndex == outputDeviceIndex) + { + return smAdapters[i]; + } + } + } + + return NULL; +} + GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type, const char* outputDevice) { GFXAdapter* adapter = GFXInit::getAdapterOfType(type, outputDevice); @@ -219,6 +235,27 @@ GFXAdapter* GFXInit::chooseAdapter( GFXAdapterType type, const char* outputDevic return adapter; } +GFXAdapter* GFXInit::chooseAdapter(GFXAdapterType type, S32 outputDeviceIndex) +{ + GFXAdapter* adapter = GFXInit::getAdapterOfType(type, outputDeviceIndex); + + if (!adapter && type != OpenGL) + { + Con::errorf("The requested renderer, %s, doesn't seem to be available." + " Trying the default, OpenGL.", getAdapterNameFromType(type)); + adapter = GFXInit::getAdapterOfType(OpenGL, outputDeviceIndex); + } + + if (!adapter) + { + Con::errorf("The OpenGL renderer doesn't seem to be available. Trying the GFXNulDevice."); + adapter = GFXInit::getAdapterOfType(NullDevice, 0); + } + + AssertFatal(adapter, "There is no rendering device available whatsoever."); + return adapter; +} + const char* GFXInit::getAdapterNameFromType(GFXAdapterType type) { // must match GFXAdapterType order @@ -256,8 +293,19 @@ GFXAdapter *GFXInit::getBestAdapterChoice() // Get the user's preference for device... const String renderer = Con::getVariable("$pref::Video::displayDevice"); const String outputDevice = Con::getVariable("$pref::Video::displayOutputDevice"); - GFXAdapterType adapterType = getAdapterTypeFromName(renderer.c_str()); - GFXAdapter *adapter = chooseAdapter(adapterType, outputDevice.c_str()); + const String adapterDevice = Con::getVariable("$Video::forceDisplayAdapter"); + + GFXAdapterType adapterType = getAdapterTypeFromName(renderer.c_str());; + GFXAdapter *adapter; + + if (adapterDevice.isEmpty()) + { + adapter = chooseAdapter(adapterType, outputDevice.c_str()); + } + else + { + adapter = chooseAdapter(adapterType, dAtoi(adapterDevice.c_str())); + } // Did they have one? Return it. if(adapter) diff --git a/Engine/source/gfx/gfxInit.h b/Engine/source/gfx/gfxInit.h index f2be9dbf7..73cdbba02 100644 --- a/Engine/source/gfx/gfxInit.h +++ b/Engine/source/gfx/gfxInit.h @@ -74,10 +74,16 @@ public: /// This method never returns NULL. static GFXAdapter *chooseAdapter( GFXAdapterType type, const char* outputDevice); + /// Override which chooses an adapter based on an index instead + static GFXAdapter *chooseAdapter( GFXAdapterType type, S32 outputDeviceIndex ); + /// Gets the first adapter of the requested type (and on the requested output device) /// from the list of enumerated adapters. Should only call this after a call to /// enumerateAdapters. static GFXAdapter *getAdapterOfType( GFXAdapterType type, const char* outputDevice ); + + /// Override which gets an adapter based on an index instead + static GFXAdapter *getAdapterOfType( GFXAdapterType type, S32 outputDeviceIndex ); /// Converts a GFXAdapterType to a string name. Useful for writing out prefs static const char *getAdapterNameFromType( GFXAdapterType type ); diff --git a/Engine/source/gfx/gfxTextureProfile.h b/Engine/source/gfx/gfxTextureProfile.h index 95bc17944..d4840cd26 100644 --- a/Engine/source/gfx/gfxTextureProfile.h +++ b/Engine/source/gfx/gfxTextureProfile.h @@ -100,7 +100,10 @@ public: /// of a target texture after presentation or deactivated. /// /// This is mainly a depth buffer optimization. - NoDiscard = BIT(10) + NoDiscard = BIT(10), + + /// Texture is managed by another process, thus should not be modified + NoModify = BIT(11) }; @@ -164,6 +167,7 @@ public: inline bool noMip() const { return testFlag(NoMipmap); } inline bool isPooled() const { return testFlag(Pooled); } inline bool canDiscard() const { return !testFlag(NoDiscard); } + inline bool canModify() const { return !testFlag(NoModify); } private: /// These constants control the packing for the profile; if you add flags, types, or diff --git a/Engine/source/gui/3d/guiTSControl.cpp b/Engine/source/gui/3d/guiTSControl.cpp index 02d93690f..d7222dcc2 100644 --- a/Engine/source/gui/3d/guiTSControl.cpp +++ b/Engine/source/gui/3d/guiTSControl.cpp @@ -37,6 +37,7 @@ #include "gfx/gfxTransformSaver.h" #include "gfx/gfxDrawUtil.h" #include "gfx/gfxDebugEvent.h" +#include "core/stream/fileStream.h" GFXTextureObject *gLastStereoTexture = NULL; @@ -569,7 +570,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) DebugDrawer::get()->render(); // Render the canvas overlay if its available - if (mRenderStyle == RenderStyleStereoSideBySide && mStereoGuiTarget.getPointer()) + if (false && mRenderStyle == RenderStyleStereoSideBySide && mStereoGuiTarget.getPointer()) { GFXDEBUGEVENT_SCOPE( StereoGui_Render, ColorI( 255, 0, 0 ) ); MatrixF proj(1); @@ -638,7 +639,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) GFXStateBlockDesc bitmapStretchSR; bitmapStretchSR.setCullMode(GFXCullNone); bitmapStretchSR.setZReadWrite(false, false); - bitmapStretchSR.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); + bitmapStretchSR.setBlend(false , GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); bitmapStretchSR.samplersDefined = true; bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear(); @@ -666,11 +667,78 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) GFX->setCurrentRenderStyle(prevRenderStyle); GFX->setCurrentProjectionOffset(prevProjectionOffset); + GFX->updateStates(true); if(mRenderStyle == RenderStyleStereoSideBySide && gLastStereoTexture) { + GFX->setWorldMatrix(MatrixF(1)); + GFX->setViewMatrix(MatrixF::Identity); GFX->setClipRect(updateRect); - GFX->getDrawUtil()->drawBitmapStretch(gLastStereoTexture, updateRect); + + GFX->getDrawUtil()->drawRectFill(RectI(Point2I(0,0), Point2I(1024, 768)), ColorI::BLACK); + GFX->getDrawUtil()->drawRect(RectI(Point2I(0, 0), Point2I(1024, 768)), ColorI::RED); + + if (!mStereoOverlayVB.getPointer()) + { + mStereoOverlayVB.set(GFX, 4, GFXBufferTypeStatic); + GFXVertexPCT *verts = mStereoOverlayVB.lock(0, 4); + + F32 texLeft = 0.0f; + F32 texRight = 1.0f; + F32 texTop = 1.0f; + F32 texBottom = 0.0f; + + F32 rectWidth = 1024.0; + F32 rectHeight = 768.0; + + F32 screenLeft = 0; + F32 screenRight = rectWidth; + F32 screenTop = 0; + F32 screenBottom = rectHeight; + + const F32 fillConv = 0.0f; + const F32 frustumDepthAdjusted = 0.0f; + verts[0].point.set(screenLeft - fillConv, screenTop - fillConv, 0.f); + verts[1].point.set(screenRight - fillConv, screenTop - fillConv, 0.f); + verts[2].point.set(screenLeft - fillConv, screenBottom - fillConv, 0.f); + verts[3].point.set(screenRight - fillConv, screenBottom - fillConv, 0.f); + + verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI(255,255,255,255); + + verts[0].texCoord.set(texLeft, texTop); + verts[1].texCoord.set(texRight, texTop); + verts[2].texCoord.set(texLeft, texBottom); + verts[3].texCoord.set(texRight, texBottom); + + mStereoOverlayVB.unlock(); + } + + if (!mStereoGuiSB.getPointer()) + { + // DrawBitmapStretchSR + GFXStateBlockDesc bitmapStretchSR; + bitmapStretchSR.setCullMode(GFXCullNone); + bitmapStretchSR.setZReadWrite(false, false); + bitmapStretchSR.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); + bitmapStretchSR.samplersDefined = true; + + bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear(); + bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint; + bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint; + bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint; + + mStereoGuiSB = GFX->createStateBlock(bitmapStretchSR); + } + //static GFXTexHandle texHandle("art/gui/splash", &GFXDefaultPersistentProfile, avar("%s() - mTextureNormal (line %d)", __FUNCTION__, __LINE__)); + GFX->setVertexBuffer(mStereoOverlayVB); + GFX->setStateBlock(mStereoGuiSB); + GFX->setTexture(0, gLastStereoTexture);// texHandle);// gLastStereoTexture); + GFX->setupGenericShaders(GFXDevice::GSModColorTexture); + GFX->drawPrimitive(GFXTriangleStrip, 0, 2); + + + + //GFX->getDrawUtil()->drawBitmapStretch(gLastStereoTexture, updateRect); } // Allow subclasses to render 2D elements. diff --git a/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp b/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp index 4eabfd1ed..50f153b12 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp +++ b/Engine/source/platform/input/oculusVR/oculusVRDevice.cpp @@ -156,26 +156,27 @@ void OculusVRDevice::buildCodeTable() OculusVRSensorDevice::buildCodeTable(); } -void OculusVRDevice::addHMDDevice(ovrHmd hmd) +void OculusVRDevice::addHMDDevice(ovrHmd hmd, ovrGraphicsLuid luid) { if(!hmd) return; OculusVRHMDDevice* hmdd = new OculusVRHMDDevice(); - hmdd->set(hmd,mHMDDevices.size()); + hmdd->set(hmd, luid, mHMDDevices.size()); mHMDDevices.push_back(hmdd); - Con::printf(" HMD found: %s by %s [v%d]", hmd->ProductName, hmd->Manufacturer, hmd->Type); + ovrHmdDesc desc = ovr_GetHmdDesc(hmd); + Con::printf(" HMD found: %s by %s [v%d]", desc.ProductName, desc.Manufacturer, desc.Type); } void OculusVRDevice::createSimulatedHMD() -{ +{/* TOFIX OculusVRHMDDevice* hmdd = new OculusVRHMDDevice(); - ovrHmd hmd = ovrHmd_CreateDebug(ovrHmd_DK2); + ovrHmd hmd = ovr_CreateDebug(ovrHmd_DK2); hmdd->set(hmd,mHMDDevices.size()); mHMDDevices.push_back(hmdd); - Con::printf(" HMD simulated: %s by %s [v%d]", hmdd->getProductName(), hmdd->getManufacturer(), hmdd->getVersion()); + Con::printf(" HMD simulated: %s by %s [v%d]", hmdd->getProductName(), hmdd->getManufacturer(), hmdd->getVersion()); */ } bool OculusVRDevice::enable() @@ -185,16 +186,17 @@ bool OculusVRDevice::enable() Con::printf("Oculus VR Device Init:"); - if(sOcculusEnabled && ovr_Initialize()) + if(sOcculusEnabled && OVR_SUCCESS(ovr_Initialize(0))) { mEnabled = true; // Enumerate HMDs and pick the first one - ovrHmd hmd = ovrHmd_Create(0); - if(hmd) + ovrHmd hmd; + ovrGraphicsLuid luid; + if(OVR_SUCCESS(ovr_Create(&hmd, &luid))) { // Add the HMD to our list - addHMDDevice(hmd); + addHMDDevice(hmd, luid); setActive(true); } @@ -700,7 +702,7 @@ DefineEngineFunction(getOVRHMDVersion, S32, (S32 index),, return hmd->getVersion(); } -DefineEngineFunction(getOVRHMDDisplayDeviceName, const char*, (S32 index),, +DefineEngineFunction(getOVRHMDDisplayDeviceType, const char*, (S32 index),, "@brief Windows display device name used in EnumDisplaySettings/CreateDC.\n\n" "@param index The HMD index.\n" "@return The name of the HMD display device, if any.\n" @@ -717,7 +719,7 @@ DefineEngineFunction(getOVRHMDDisplayDeviceName, const char*, (S32 index),, return ""; } - return hmd->getDisplayDeviceName(); + return hmd->getDisplayDeviceType(); } DefineEngineFunction(getOVRHMDDisplayDeviceId, S32, (S32 index),, @@ -740,26 +742,6 @@ DefineEngineFunction(getOVRHMDDisplayDeviceId, S32, (S32 index),, return hmd->getDisplayDeviceId(); } -DefineEngineFunction(getOVRHMDDisplayDesktopPos, Point2I, (S32 index),, - "@brief Desktop coordinate position of the screen (can be negative; may not be present on all platforms).\n\n" - "@param index The HMD index.\n" - "@return Position of the screen.\n" - "@ingroup Game") -{ - if(!ManagedSingleton::instanceOrNull()) - { - return Point2I::Zero; - } - - const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index); - if(!hmd) - { - return Point2I::Zero; - } - - return hmd->getDesktopPosition(); -} - DefineEngineFunction(getOVRHMDResolution, Point2I, (S32 index),, "@brief Provides the OVR HMD screen resolution.\n\n" "@param index The HMD index.\n" diff --git a/Engine/source/platform/input/oculusVR/oculusVRDevice.h b/Engine/source/platform/input/oculusVR/oculusVRDevice.h index 695b435f1..c1ee642a2 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRDevice.h +++ b/Engine/source/platform/input/oculusVR/oculusVRDevice.h @@ -33,7 +33,7 @@ #include "math/mQuat.h" #include "math/mPoint4.h" #include "gfx/gfxDevice.h" -#include "OVR_CAPI_0_5_0.h" +#include "OVR_CAPI_0_8_0.h" #define DEFAULT_RIFT_UNIT 0 @@ -83,6 +83,9 @@ protected: /// Which HMD is the active one U32 mActiveDeviceId; + /// Device id we need to use to hook up with oculus + ovrGraphicsLuid mLuid; + protected: void cleanUp(); @@ -90,7 +93,7 @@ protected: /// Input Event Manager void buildCodeTable(); - void addHMDDevice(ovrHmd hmd); + void addHMDDevice(ovrHmd hmd, ovrGraphicsLuid luid); void createSimulatedHMD(); diff --git a/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp b/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp index d9a8ca074..2d1bef8f9 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp +++ b/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp @@ -26,27 +26,144 @@ #include "postFx/postEffectCommon.h" #include "gui/core/guiCanvas.h" #include "platform/input/oculusVR/oculusVRUtil.h" +#include "core/stream/fileStream.h" -#include "gfx/D3D9/gfxD3D9Device.h" -// Use D3D9 for win32 + +#include "gfx/D3D11/gfxD3D11Device.h" +#include "gfx/D3D11/gfxD3D11EnumTranslate.h" +#include "gfx/gfxStringEnumTranslate.h" +#undef D3D11 + +// Use D3D11 for win32 #ifdef TORQUE_OS_WIN -#define OVR_D3D_VERSION 9 +#define OVR_D3D_VERSION 11 #include "OVR_CAPI_D3D.h" #define OCULUS_USE_D3D #else #include "OVR_CAPI_GL.h" #define OCULUS_USE_GL #endif - extern GFXTextureObject *gLastStereoTexture; -OculusVRHMDDevice::OculusVRHMDDevice() : -mWindowSize(1280,800) +struct OculusTexture +{ + virtual void AdvanceToNextTexture() = 0; + + virtual ~OculusTexture() { + } +}; + +//------------------------------------------------------------ +// ovrSwapTextureSet wrapper class that also maintains the render target views +// needed for D3D11 rendering. +struct D3D11OculusTexture : public OculusTexture +{ + ovrHmd hmd; + ovrSwapTextureSet * TextureSet; + static const int TextureCount = 2; + GFXTexHandle TexRtv[TextureCount]; + GFXDevice *Owner; + + D3D11OculusTexture(GFXDevice* owner) : + hmd(nullptr), + TextureSet(nullptr), + Owner(owner) + { + TexRtv[0] = TexRtv[1] = nullptr; + } + + bool Init(ovrHmd _hmd, int sizeW, int sizeH) + { + hmd = _hmd; + + D3D11_TEXTURE2D_DESC dsDesc; + dsDesc.Width = sizeW; + dsDesc.Height = sizeH; + dsDesc.MipLevels = 1; + dsDesc.ArraySize = 1; + dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + dsDesc.SampleDesc.Count = 1; // No multi-sampling allowed + dsDesc.SampleDesc.Quality = 0; + dsDesc.Usage = D3D11_USAGE_DEFAULT; + dsDesc.CPUAccessFlags = 0; + dsDesc.MiscFlags = 0; + dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + + + GFXD3D11Device* device = static_cast(GFX); + ovrResult result = ovr_CreateSwapTextureSetD3D11(hmd, device->mD3DDevice, &dsDesc, ovrSwapTextureSetD3D11_Typeless, &TextureSet); + if (!OVR_SUCCESS(result)) + return false; + + AssertFatal(TextureSet->TextureCount == TextureCount, "TextureCount mismatch."); + + for (int i = 0; i < TextureCount; ++i) + { + ovrD3D11Texture* tex = (ovrD3D11Texture*)&TextureSet->Textures[i]; + D3D11_RENDER_TARGET_VIEW_DESC rtvd = {}; + rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + + GFXD3D11TextureObject* object = new GFXD3D11TextureObject(GFX, &VRTextureProfile); + object->registerResourceWithDevice(GFX); + *(object->getSRViewPtr()) = tex->D3D11.pSRView; + *(object->get2DTexPtr()) = tex->D3D11.pTexture; + device->mD3DDevice->CreateRenderTargetView(tex->D3D11.pTexture, &rtvd, object->getRTViewPtr()); + + // Add refs for texture release later on + if (object->getSRView()) object->getSRView()->AddRef(); + //object->getRTView()->AddRef(); + if (object->get2DTex()) object->get2DTex()->AddRef(); + object->isManaged = true; + + // Get the actual size of the texture... + D3D11_TEXTURE2D_DESC probeDesc; + ZeroMemory(&probeDesc, sizeof(D3D11_TEXTURE2D_DESC)); + object->get2DTex()->GetDesc(&probeDesc); + + object->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0); + object->mBitmapSize = object->mTextureSize; + int fmt = probeDesc.Format; + + if (fmt == DXGI_FORMAT_R8G8B8A8_TYPELESS) + { + object->mFormat = GFXFormatR8G8B8A8; // usual case + } + else + { + // TODO: improve this. this can be very bad. + GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, fmt); + object->mFormat = (GFXFormat)fmt; + } + TexRtv[i] = object; + } + + return true; + } + + ~D3D11OculusTexture() + { + for (int i = 0; i < TextureCount; ++i) + { + SAFE_DELETE(TexRtv[i]); + } + if (TextureSet) + { + ovr_DestroySwapTextureSet(hmd, TextureSet); + } + } + + void AdvanceToNextTexture() + { + TextureSet->CurrentIndex = (TextureSet->CurrentIndex + 1) % TextureSet->TextureCount; + } +}; + + +OculusVRHMDDevice::OculusVRHMDDevice() { mIsValid = false; mDevice = NULL; - mSupportedDistortionCaps = 0; - mCurrentDistortionCaps = 0; mCurrentCaps = 0; mSupportedCaps = 0; mVsync = true; @@ -60,6 +177,7 @@ mWindowSize(1280,800) mConnection = NULL; mSensor = NULL; mActionCodeIndex = 0; + mTextureSwapSet = NULL; } OculusVRHMDDevice::~OculusVRHMDDevice() @@ -79,14 +197,14 @@ void OculusVRHMDDevice::cleanUp() if(mDevice) { - ovrHmd_Destroy(mDevice); + ovr_Destroy(mDevice); mDevice = NULL; } mIsValid = false; } -void OculusVRHMDDevice::set(ovrHmd hmd, U32 actionCodeIndex) +void OculusVRHMDDevice::set(ovrHmd hmd, ovrGraphicsLuid luid, U32 actionCodeIndex) { cleanUp(); @@ -95,50 +213,42 @@ void OculusVRHMDDevice::set(ovrHmd hmd, U32 actionCodeIndex) mDevice = hmd; - mSupportedCaps = hmd->HmdCaps; - mCurrentCaps = mSupportedCaps & (ovrHmdCap_DynamicPrediction | ovrHmdCap_LowPersistence | (!mVsync ? ovrHmdCap_NoVSync : 0)); + ovrHmdDesc desc = ovr_GetHmdDesc(hmd); + int caps = ovr_GetTrackingCaps(hmd); - mSupportedDistortionCaps = hmd->DistortionCaps; - mCurrentDistortionCaps = mSupportedDistortionCaps & (ovrDistortionCap_TimeWarp | ovrDistortionCap_Vignette | ovrDistortionCap_Overdrive); + mSupportedCaps = desc.AvailableHmdCaps; + mCurrentCaps = mSupportedCaps; - mTimewarp = mSupportedDistortionCaps & ovrDistortionCap_TimeWarp; + mTimewarp = true; // DeviceInfo - mProductName = hmd->ProductName; - mManufacturer = hmd->Manufacturer; - mVersion = hmd->FirmwareMajor; + mProductName = desc.ProductName; + mManufacturer = desc.Manufacturer; + mVersion = desc.FirmwareMajor; - mDisplayDeviceName = hmd->DisplayDeviceName; - mDisplayId = hmd->DisplayId; + // + Vector adapterList; + GFXD3D11Device::enumerateAdapters(adapterList); - mDesktopPosition.x = hmd->WindowsPos.x; - mDesktopPosition.y = hmd->WindowsPos.y; + dMemcpy(&mLuid, &luid, sizeof(mLuid)); + mDisplayId = -1; - mResolution.x = hmd->Resolution.w; - mResolution.y = hmd->Resolution.h; + for (U32 i = 0, sz = adapterList.size(); i < sz; i++) + { + GFXAdapter* adapter = adapterList[i]; + if (dMemcmp(&adapter->mLUID, &mLuid, sizeof(mLuid)) == 0) + { + mDisplayId = adapter->mIndex; + mDisplayDeviceType = "D3D11"; // TOFIX this + } + } - mProfileInterpupillaryDistance = ovrHmd_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD); - mLensSeparation = ovrHmd_GetFloat(hmd, "LensSeparation", 0); - ovrHmd_GetFloatArray(hmd, "ScreenSize", &mScreenSize.x, 2); + mResolution.x = desc.Resolution.w; + mResolution.y = desc.Resolution.h; - dMemcpy(mCurrentFovPorts, mDevice->DefaultEyeFov, sizeof(mDevice->DefaultEyeFov)); - - for (U32 i=0; i<2; i++) - { - mCurrentFovPorts[i].UpTan = mDevice->DefaultEyeFov[i].UpTan; - mCurrentFovPorts[i].DownTan = mDevice->DefaultEyeFov[i].DownTan; - mCurrentFovPorts[i].LeftTan = mDevice->DefaultEyeFov[i].LeftTan; - mCurrentFovPorts[i].RightTan = mDevice->DefaultEyeFov[i].RightTan; - } - - if (mDevice->HmdCaps & ovrHmdCap_ExtendDesktop) - { - mWindowSize = Point2I(mDevice->Resolution.w, mDevice->Resolution.h); - } - else - { - mWindowSize = Point2I(1100, 618); - } + mProfileInterpupillaryDistance = ovr_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD); + mLensSeparation = ovr_GetFloat(hmd, "LensSeparation", 0); + ovr_GetFloatArray(hmd, "ScreenSize", &mScreenSize.x, 2); mActionCodeIndex = actionCodeIndex; @@ -147,6 +257,8 @@ void OculusVRHMDDevice::set(ovrHmd hmd, U32 actionCodeIndex) mSensor = new OculusVRSensorDevice(); mSensor->set(mDevice, mActionCodeIndex); + mDebugMirrorTexture = NULL; + updateCaps(); } @@ -163,25 +275,26 @@ void OculusVRHMDDevice::setOptimalDisplaySize(GuiCanvas *canvas) PlatformWindow *window = canvas->getPlatformWindow(); GFXTarget *target = window->getGFXTarget(); - if (target && target->getSize() != mWindowSize) + Point2I requiredSize(0, 0); + + ovrHmdDesc desc = ovr_GetHmdDesc(mDevice); + ovrSizei leftSize = ovr_GetFovTextureSize(mDevice, ovrEye_Left, desc.DefaultEyeFov[0], mCurrentPixelDensity); + ovrSizei rightSize = ovr_GetFovTextureSize(mDevice, ovrEye_Right, desc.DefaultEyeFov[1], mCurrentPixelDensity); + + requiredSize.x = leftSize.w + rightSize.h; + requiredSize.y = mMax(leftSize.h, rightSize.h); + + if (target && target->getSize() != requiredSize) { GFXVideoMode newMode; newMode.antialiasLevel = 0; newMode.bitDepth = 32; newMode.fullScreen = false; newMode.refreshRate = 75; - newMode.resolution = mWindowSize; + newMode.resolution = requiredSize; newMode.wideScreen = false; window->setVideoMode(newMode); - //AssertFatal(window->getClientExtent().x == mWindowSize[0] && window->getClientExtent().y == mWindowSize[1], "Window didn't resize to correct dimensions"); - } - - // Need to move window over to the rift side of the desktop - if (mDevice->HmdCaps & ovrHmdCap_ExtendDesktop && !OculusVRDevice::smWindowDebug) - { -#ifndef OCULUS_WINDOW_DEBUG - window->setPosition(getDesktopPosition()); -#endif + //AssertFatal(window->getClientExtent().x == requiredSize.x && window->getClientExtent().y == requiredSize.y, "Window didn't resize to correct dimensions"); } } @@ -190,61 +303,165 @@ bool OculusVRHMDDevice::isDisplayingWarning() if (!mIsValid || !mDevice) return false; + return false;/* ovrHSWDisplayState displayState; ovrHmd_GetHSWDisplayState(mDevice, &displayState); - return displayState.Displayed; + return displayState.Displayed;*/ } void OculusVRHMDDevice::dismissWarning() { if (!mIsValid || !mDevice) return; - ovrHmd_DismissHSWDisplay(mDevice); + //ovr_DismissHSWDisplay(mDevice); } bool OculusVRHMDDevice::setupTargets() { - ovrFovPort eyeFov[2] = {mDevice->DefaultEyeFov[0], mDevice->DefaultEyeFov[1]}; + // Create eye render buffers + ID3D11RenderTargetView * eyeRenderTexRtv[2]; + ovrLayerEyeFov ld = { { ovrLayerType_EyeFov } }; + mRenderLayer = ld; - mRecomendedEyeTargetSize[0] = ovrHmd_GetFovTextureSize(mDevice, ovrEye_Left, eyeFov[0], mCurrentPixelDensity); - mRecomendedEyeTargetSize[1] = ovrHmd_GetFovTextureSize(mDevice, ovrEye_Right, eyeFov[1], mCurrentPixelDensity); + GFXD3D11Device* device = static_cast(GFX); - // Calculate render target size - if (mDesiredRenderingMode == GFXDevice::RS_StereoSideBySide) - { - // Setup a single texture, side-by-side viewports - Point2I rtSize( - mRecomendedEyeTargetSize[0].w + mRecomendedEyeTargetSize[1].w, - mRecomendedEyeTargetSize[0].h > mRecomendedEyeTargetSize[1].h ? mRecomendedEyeTargetSize[0].h : mRecomendedEyeTargetSize[1].h - ); + ovrHmdDesc desc = ovr_GetHmdDesc(mDevice); + for (int i = 0; i < 2; i++) + { + mRenderLayer.Fov[i] = desc.DefaultEyeFov[i]; + mRenderLayer.Viewport[i].Size = ovr_GetFovTextureSize(mDevice, (ovrEyeType)i, mRenderLayer.Fov[i], mCurrentPixelDensity); + mEyeRenderDesc[i] = ovr_GetRenderDesc(mDevice, (ovrEyeType_)(ovrEye_Left+i), mRenderLayer.Fov[i]); + } - GFXFormat targetFormat = GFX->getActiveRenderTarget()->getFormat(); - mRTFormat = targetFormat; + ovrSizei recommendedEyeTargetSize[2]; + recommendedEyeTargetSize[0] = mRenderLayer.Viewport[0].Size; + recommendedEyeTargetSize[1] = mRenderLayer.Viewport[1].Size; - rtSize = generateRenderTarget(mStereoRT, mStereoTexture, mStereoDepthTexture, rtSize); - - // Left - mEyeRenderSize[0] = rtSize; - mEyeRT[0] = mStereoRT; - mEyeTexture[0] = mStereoTexture; - mEyeViewport[0] = RectI(Point2I(0,0), Point2I((mRecomendedEyeTargetSize[0].w+1)/2, mRecomendedEyeTargetSize[0].h)); + if (mTextureSwapSet) + { + delete mTextureSwapSet; + mTextureSwapSet = NULL; + } - // Right - mEyeRenderSize[1] = rtSize; - mEyeRT[1] = mStereoRT; - mEyeTexture[1] = mStereoTexture; - mEyeViewport[1] = RectI(Point2I((mRecomendedEyeTargetSize[0].w+1)/2,0), Point2I((mRecomendedEyeTargetSize[1].w+1)/2, mRecomendedEyeTargetSize[1].h)); + // Calculate render target size + if (mDesiredRenderingMode == GFXDevice::RS_StereoSideBySide) + { + // Setup a single texture, side-by-side viewports + Point2I rtSize( + recommendedEyeTargetSize[0].w + recommendedEyeTargetSize[1].w, + recommendedEyeTargetSize[0].h > recommendedEyeTargetSize[1].h ? recommendedEyeTargetSize[0].h : recommendedEyeTargetSize[1].h + ); - gLastStereoTexture = mEyeTexture[0]; - } - else - { - // No rendering, abort! - return false; - } + GFXFormat targetFormat = GFX->getActiveRenderTarget()->getFormat(); + mRTFormat = targetFormat; - return true; + rtSize = generateRenderTarget(mStereoRT, mStereoDepthTexture, rtSize); + + // Generate the swap texture we need to store the final image + D3D11OculusTexture* tex = new D3D11OculusTexture(GFX); + if (tex->Init(mDevice, rtSize.x, rtSize.y)) + { + mTextureSwapSet = tex; + } + + mRenderLayer.ColorTexture[0] = tex->TextureSet; + mRenderLayer.ColorTexture[1] = tex->TextureSet; + + mRenderLayer.Viewport[0].Pos.x = 0; + mRenderLayer.Viewport[0].Pos.y = 0; + mRenderLayer.Viewport[1].Pos.x = (rtSize.x + 1) / 2; + mRenderLayer.Viewport[1].Pos.y = 0; + + // Left + mEyeRT[0] = mStereoRT; + 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)); + + // Right + mEyeRT[1] = mStereoRT; + 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)); + + gLastStereoTexture = NULL; + + + GFXD3D11Device* device = static_cast(GFX); + + D3D11_TEXTURE2D_DESC dsDesc; + dsDesc.Width = rtSize.x; + dsDesc.Height = rtSize.y; + dsDesc.MipLevels = 1; + dsDesc.ArraySize = 1; + dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + dsDesc.SampleDesc.Count = 1; + dsDesc.SampleDesc.Quality = 0; + dsDesc.Usage = D3D11_USAGE_DEFAULT; + dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + dsDesc.CPUAccessFlags = 0; + dsDesc.MiscFlags = 0; + + // Create typeless when we are rendering as non-sRGB since we will override the texture format in the RTV + bool reinterpretSrgbAsLinear = true; + unsigned compositorTextureFlags = 0; + if (reinterpretSrgbAsLinear) + compositorTextureFlags |= ovrSwapTextureSetD3D11_Typeless; + + ovrResult result = ovr_CreateMirrorTextureD3D11(mDevice, device->mD3DDevice, &dsDesc, compositorTextureFlags, &mDebugMirrorTexture); + + if (result == ovrError_DisplayLost || !mDebugMirrorTexture) + { + AssertFatal(false, "Something went wrong"); + return NULL; + } + + // Create texture handle so we can render it in-game + ovrD3D11Texture* mirror_tex = (ovrD3D11Texture*)mDebugMirrorTexture; + D3D11_RENDER_TARGET_VIEW_DESC rtvd = {}; + rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + + GFXD3D11TextureObject* object = new GFXD3D11TextureObject(GFX, &VRTextureProfile); + object->registerResourceWithDevice(GFX); + *(object->getSRViewPtr()) = mirror_tex->D3D11.pSRView; + *(object->get2DTexPtr()) = mirror_tex->D3D11.pTexture; + device->mD3DDevice->CreateRenderTargetView(mirror_tex->D3D11.pTexture, &rtvd, object->getRTViewPtr()); + + + // Add refs for texture release later on + if (object->getSRView()) object->getSRView()->AddRef(); + //object->getRTView()->AddRef(); + if (object->get2DTex()) object->get2DTex()->AddRef(); + object->isManaged = true; + + // Get the actual size of the texture... + D3D11_TEXTURE2D_DESC probeDesc; + ZeroMemory(&probeDesc, sizeof(D3D11_TEXTURE2D_DESC)); + object->get2DTex()->GetDesc(&probeDesc); + + object->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0); + object->mBitmapSize = object->mTextureSize; + int fmt = probeDesc.Format; + + if (fmt == DXGI_FORMAT_R8G8B8A8_TYPELESS) + { + object->mFormat = GFXFormatR8G8B8A8; // usual case + } + else + { + // TODO: improve this. this can be very bad. + GFXREVERSE_LOOKUP(GFXD3D11TextureFormat, GFXFormat, fmt); + object->mFormat = (GFXFormat)fmt; + } + + mDebugMirrorTextureHandle = object; + gLastStereoTexture = mDebugMirrorTextureHandle; + } + else + { + // No rendering, abort! + return false; + } + + return true; } String OculusVRHMDDevice::dumpMetrics() @@ -261,17 +478,14 @@ String OculusVRHMDDevice::dumpMetrics() F32 ipd = this->getIPD(); U32 lastStatus = mSensor->getLastTrackingStatus(); - 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, Disort:%s%s%s", + 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", mActionCodeIndex, rot.x, rot.y, rot.z, pos.x, pos.y, pos.z, eyeFov[0].upTan, eyeFov[0].downTan, eyeFov[0].leftTan, eyeFov[0].rightTan, eyeFov[1].upTan, eyeFov[1].downTan, eyeFov[1].leftTan, eyeFov[1].rightTan, getIPD(), lastStatus & ovrStatus_OrientationTracked ? " ORIENT" : "", - lastStatus & ovrStatus_PositionTracked ? " POS" : "", - mCurrentDistortionCaps & ovrDistortionCap_TimeWarp ? " TIMEWARP" : "", - mCurrentDistortionCaps & ovrDistortionCap_Vignette ? " VIGNETTE" : "", - mCurrentDistortionCaps & ovrDistortionCap_Overdrive ? " OVERDRIVE" : ""); + lastStatus & ovrStatus_PositionTracked ? " POS" : ""); return sb.data(); } @@ -292,82 +506,23 @@ void OculusVRHMDDevice::updateRenderInfo() return; PlatformWindow *window = mDrawCanvas->getPlatformWindow(); - ovrFovPort eyeFov[2] = {mDevice->DefaultEyeFov[0], mDevice->DefaultEyeFov[1]}; + + ovrHmdDesc desc = ovr_GetHmdDesc(mDevice); // Update window size if it's incorrect Point2I backbufferSize = mDrawCanvas->getBounds().extent; - // Reset - ovrHmd_ConfigureRendering(mDevice, NULL, 0, NULL, NULL); - -#ifdef OCULUS_USE_D3D - // Generate render target textures - GFXD3D9Device *d3d9GFX = dynamic_cast(GFX); - if (d3d9GFX) - { - ovrD3D9Config cfg; - cfg.D3D9.Header.API = ovrRenderAPI_D3D9; - cfg.D3D9.Header.Multisample = 0; - cfg.D3D9.Header.BackBufferSize = OVR::Sizei(backbufferSize.x, backbufferSize.y); - cfg.D3D9.pDevice = d3d9GFX->getDevice(); - cfg.D3D9.pDevice->GetSwapChain(0, &cfg.D3D9.pSwapChain); - - // Finally setup! - if (!setupTargets()) - { - onDeviceDestroy(); - return; - } - - ovrHmd_AttachToWindow(mDevice, window->getPlatformDrawable(), NULL, NULL); - - if (!ovrHmd_ConfigureRendering( mDevice, &cfg.Config, mCurrentDistortionCaps, eyeFov, mEyeRenderDesc )) - { - Con::errorf("Couldn't configure oculus rendering!"); - return; - } - } -#endif - -#ifdef OCULUS_USE_GL - // Generate render target textures - GFXGLDevice *glGFX = dynamic_cast(GFX); - if (glGFX) - { - ovrGLConfig cfg; - cfg.OGL.Header.API = ovrRenderAPI_OpenGL; - cfg.OGL.Header.Multisample = 0; - cfg.OGL.Header.BackBufferSize = OVR::Sizei(backbufferSize.x, backbufferSize.y); - -#ifdef WIN32 - cfg.OGL.Window = GetActiveWindow();//window->getPlatformDrawable(); - cfg.OGL.DC = wglGetCurrentDC(); -#else - cfg.OGL.Disp = NULL; -#endif - - // Finally setup! - if (!setupTargets()) - { - onDeviceDestroy(); - return; - } - - ovrHmd_AttachToWindow(mDevice, window->getPlatformDrawable(), NULL, NULL); - - if (!ovrHmd_ConfigureRendering( mDevice, &cfg.Config, mCurrentDistortionCaps, eyeFov, mEyeRenderDesc )) - { - Con::errorf("Couldn't configure oculus rendering!"); - return; - } - } -#endif - + // Finally setup! + if (!setupTargets()) + { + onDeviceDestroy(); + return; + } mRenderConfigurationDirty = false; } -Point2I OculusVRHMDDevice::generateRenderTarget(GFXTextureTargetRef &target, GFXTexHandle &texture, GFXTexHandle &depth, Point2I desiredSize) +Point2I OculusVRHMDDevice::generateRenderTarget(GFXTextureTargetRef &target, GFXTexHandle &depth, Point2I desiredSize) { // Texture size that we already have might be big enough. Point2I newRTSize; @@ -402,12 +557,12 @@ Point2I OculusVRHMDDevice::generateRenderTarget(GFXTextureTargetRef &target, GFX newRTSize.setMax(Point2I(64, 64)); // Stereo RT needs to be the same size as the recommended RT - if ( newRT || texture.getWidthHeight() != newRTSize ) + /*if ( newRT || mDebugStereoTexture.getWidthHeight() != newRTSize ) { - texture.set( newRTSize.x, newRTSize.y, mRTFormat, &VRTextureProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); - target->attachTexture( GFXTextureTarget::Color0, texture ); - Con::printf("generateRenderTarget generated %x", texture.getPointer()); - } + mDebugStereoTexture.set( newRTSize.x, newRTSize.y, mRTFormat, &VRTextureProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); + target->attachTexture( GFXTextureTarget::Color0, mDebugStereoTexture); + Con::printf("generateRenderTarget generated %x", mDebugStereoTexture.getPointer()); + }*/ if ( depth.getWidthHeight() != newRTSize ) { @@ -424,6 +579,13 @@ void OculusVRHMDDevice::clearRenderTargets() mStereoRT = NULL; mEyeRT[0] = NULL; mEyeRT[1] = NULL; + + if (mDebugMirrorTexture) + { + ovr_DestroyMirrorTexture(mDevice, mDebugMirrorTexture); + mDebugMirrorTexture = NULL; + mDebugMirrorTextureHandle = NULL; + } } void OculusVRHMDDevice::updateCaps() @@ -431,34 +593,7 @@ void OculusVRHMDDevice::updateCaps() if (!mIsValid || !mDevice) return; - U32 oldDistortionCaps = mCurrentDistortionCaps; - - // Distortion - if (mTimewarp) - { - mCurrentDistortionCaps |= ovrDistortionCap_TimeWarp; - } - else - { - mCurrentDistortionCaps &= ~ovrDistortionCap_TimeWarp; - } - - if (oldDistortionCaps != mCurrentDistortionCaps) - { - mRenderConfigurationDirty = true; - } - - // Device - if (!mVsync) - { - mCurrentCaps |= ovrHmdCap_NoVSync; - } - else - { - mCurrentCaps &= ~ovrHmdCap_NoVSync; - } - - ovrHmd_SetEnabledCaps(mDevice, mCurrentCaps); + ovr_SetEnabledCaps(mDevice, mCurrentCaps); } static bool sInFrame = false; // protects against recursive onStartFrame calls @@ -469,108 +604,64 @@ void OculusVRHMDDevice::onStartFrame() return; sInFrame = true; - -#ifndef OCULUS_DEBUG_FRAME - ovrHmd_BeginFrame(mDevice, 0); -#endif ovrVector3f hmdToEyeViewOffset[2] = { mEyeRenderDesc[0].HmdToEyeViewOffset, mEyeRenderDesc[1].HmdToEyeViewOffset }; - ovrHmd_GetEyePoses(mDevice, 0, hmdToEyeViewOffset, mCurrentEyePoses, &mLastTrackingState); + ovrTrackingState hmdState = ovr_GetTrackingState(mDevice, 0, ovrTrue); + ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewOffset, mRenderLayer.RenderPose); for (U32 i=0; i<2; i++) { - mCurrentEyePoses[i].Position.x *= OculusVRDevice::smPositionTrackingScale; - mCurrentEyePoses[i].Position.y *= OculusVRDevice::smPositionTrackingScale; - mCurrentEyePoses[i].Position.z *= OculusVRDevice::smPositionTrackingScale; + mRenderLayer.RenderPose[i].Position.x *= OculusVRDevice::smPositionTrackingScale; + mRenderLayer.RenderPose[i].Position.y *= OculusVRDevice::smPositionTrackingScale; + mRenderLayer.RenderPose[i].Position.z *= OculusVRDevice::smPositionTrackingScale; } + mRenderLayer.SensorSampleTime = ovr_GetTimeInSeconds(); + + // Set current dest texture on stereo render target + D3D11OculusTexture* texSwap = (D3D11OculusTexture*)mTextureSwapSet; + mStereoRT->attachTexture(GFXTextureTarget::Color0, texSwap->TexRtv[texSwap->TextureSet->CurrentIndex]); + sInFrame = false; mFrameReady = true; } void OculusVRHMDDevice::onEndFrame() { - if (!mIsValid || !mDevice || !mDrawCanvas || sInFrame || !mFrameReady) + if (!mIsValid || !mDevice || !mDrawCanvas || sInFrame || !mFrameReady || !mTextureSwapSet) return; Point2I eyeSize; GFXTarget *windowTarget = mDrawCanvas->getPlatformWindow()->getGFXTarget(); -#ifndef OCULUS_DEBUG_FRAME - -#ifdef OCULUS_USE_D3D - GFXD3D9Device *d3d9GFX = dynamic_cast(GFX); - if (d3d9GFX && mEyeRT[0].getPointer()) - { - // Left - ovrD3D9Texture eyeTextures[2]; - eyeSize = mEyeTexture[0].getWidthHeight(); - eyeTextures[0].D3D9.Header.API = ovrRenderAPI_D3D9; - eyeTextures[0].D3D9.Header.RenderViewport.Pos.x = mEyeViewport[0].point.x; - eyeTextures[0].D3D9.Header.RenderViewport.Pos.y = mEyeViewport[0].point.y; - eyeTextures[0].D3D9.Header.RenderViewport.Size.w = mEyeViewport[0].extent.x; - eyeTextures[0].D3D9.Header.RenderViewport.Size.h = mEyeViewport[0].extent.y; - eyeTextures[0].D3D9.Header.TextureSize.w = eyeSize.x; - eyeTextures[0].D3D9.Header.TextureSize.h = eyeSize.y; - eyeTextures[0].D3D9.pTexture = mEyeRT[0].getPointer() ? static_cast(mEyeTexture[0].getPointer())->get2DTex() : NULL; + GFXD3D11Device *d3d11GFX = dynamic_cast(GFX); - // Right - eyeSize = mEyeTexture[1].getWidthHeight(); - eyeTextures[1].D3D9.Header.API = ovrRenderAPI_D3D9; - eyeTextures[1].D3D9.Header.RenderViewport.Pos.x = mEyeViewport[1].point.x; - eyeTextures[1].D3D9.Header.RenderViewport.Pos.y = mEyeViewport[1].point.y; - eyeTextures[1].D3D9.Header.RenderViewport.Size.w = mEyeViewport[1].extent.x; - eyeTextures[1].D3D9.Header.RenderViewport.Size.h = mEyeViewport[1].extent.y; - eyeTextures[1].D3D9.Header.TextureSize.w = eyeSize.x; - eyeTextures[1].D3D9.Header.TextureSize.h = eyeSize.y; - eyeTextures[1].D3D9.pTexture = mEyeRT[0].getPointer() ? static_cast(mEyeTexture[1].getPointer())->get2DTex() : NULL; + ovrViewScaleDesc viewScaleDesc; + ovrVector3f hmdToEyeViewOffset[2] = { mEyeRenderDesc[0].HmdToEyeViewOffset, mEyeRenderDesc[1].HmdToEyeViewOffset }; + viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; + viewScaleDesc.HmdToEyeViewOffset[0] = hmdToEyeViewOffset[0]; + viewScaleDesc.HmdToEyeViewOffset[1] = hmdToEyeViewOffset[1]; - // Submit! - GFX->disableShaders(); - GFX->setActiveRenderTarget(windowTarget); - GFX->clear(GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI(255,0,0), 1.0f, 0); - ovrHmd_EndFrame(mDevice, mCurrentEyePoses, (ovrTexture*)(&eyeTextures[0])); - } -#endif + ovrLayerDirect ld = { { ovrLayerType_Direct } }; + mDebugRenderLayer = ld; -#ifdef OCULUS_USE_GL - GFXGLDevice *glGFX = dynamic_cast(GFX); - if (glGFX && mEyeRT[0].getPointer()) - { - // Left - ovrGLTexture eyeTextures[2]; - eyeSize = mEyeTexture[0].getWidthHeight(); - eyeTextures[0].OGL.Header.API = ovrRenderAPI_GL; - eyeTextures[0].OGL.Header.RenderViewport.Pos.x = mEyeViewport[0].point.x; - eyeTextures[0].OGL.Header.RenderViewport.Pos.y = mEyeViewport[0].point.y; - eyeTextures[0].OGL.Header.RenderViewport.Size.w = mEyeViewport[0].extent.x; - eyeTextures[0].OGL.Header.RenderViewport.Size.h = mEyeViewport[0].extent.y; - eyeTextures[0].OGL.Header.TextureSize.w = eyeSize.x; - eyeTextures[0].OGL.Header.TextureSize.h = eyeSize.y; - eyeTextures[0].OGL.TexId = mEyeRT[0].getPointer() ? static_cast(mEyeTexture[0].getPointer())->getHandle() : 0; + mDebugRenderLayer.ColorTexture[0] = mRenderLayer.ColorTexture[0]; + mDebugRenderLayer.ColorTexture[1] = mRenderLayer.ColorTexture[1]; + mDebugRenderLayer.Viewport[0] = mRenderLayer.Viewport[0]; + mDebugRenderLayer.Viewport[1] = mRenderLayer.Viewport[1]; - // Right - eyeSize = mEyeTexture[1].getWidthHeight(); - eyeTextures[1].OGL.Header.API = ovrRenderAPI_GL; - eyeTextures[1].OGL.Header.RenderViewport.Pos.x = mEyeViewport[1].point.x; - eyeTextures[1].OGL.Header.RenderViewport.Pos.y = mEyeViewport[1].point.y; - eyeTextures[1].OGL.Header.RenderViewport.Size.w = mEyeViewport[1].extent.x; - eyeTextures[1].OGL.Header.RenderViewport.Size.h = mEyeViewport[1].extent.y; - eyeTextures[1].OGL.Header.TextureSize.w = eyeSize.x; - eyeTextures[1].OGL.Header.TextureSize.h = eyeSize.y; - eyeTextures[0].OGL.TexId = mEyeRT[1].getPointer() ? static_cast(mEyeTexture[1].getPointer())->getHandle() : 0; + // TODO: use ovrViewScaleDesc + ovrLayerHeader* layers = &mRenderLayer.Header; + ovrResult result = ovr_SubmitFrame(mDevice, 0, &viewScaleDesc, &layers, 1); + mTextureSwapSet->AdvanceToNextTexture(); - // Submit! - GFX->disableShaders(); + if (OVR_SUCCESS(result)) + { + int woo = 1; + } - GFX->setActiveRenderTarget(windowTarget); - GFX->clear(GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI(255,0,0), 1.0f, 0); - ovrHmd_EndFrame(mDevice, mCurrentEyePoses, (ovrTexture*)(&eyeTextures[0])); - } -#endif - -#endif + // TODO: render preview in display? mFrameReady = false; } @@ -578,7 +669,7 @@ void OculusVRHMDDevice::onEndFrame() void OculusVRHMDDevice::getFrameEyePose(DisplayPose *outPose, U32 eyeId) const { // Directly set the rotation and position from the eye transforms - ovrPosef pose = mCurrentEyePoses[eyeId]; + ovrPosef pose = mRenderLayer.RenderPose[eyeId]; OVR::Quatf orientation = pose.Orientation; const OVR::Vector3f position = pose.Position; @@ -605,18 +696,17 @@ void OculusVRHMDDevice::onDeviceDestroy() mEyeRT[1]->zombify(); } + if (mTextureSwapSet) + { + delete mTextureSwapSet; + mTextureSwapSet = NULL; + } + mStereoRT = NULL; - mStereoTexture = NULL; mStereoDepthTexture = NULL; - mEyeTexture[0] = NULL; - mEyeDepthTexture[0] = NULL; - mEyeTexture[1] = NULL; - mEyeDepthTexture[1] = NULL; mEyeRT[0] = NULL; mEyeRT[1] = NULL; mRenderConfigurationDirty = true; - - ovrHmd_ConfigureRendering(mDevice, NULL, 0, NULL, NULL); } diff --git a/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.h b/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.h index 996a0ca14..13a5533b2 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.h +++ b/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.h @@ -34,12 +34,14 @@ #include "math/mRect.h" #include "gfx/gfxDevice.h" -#include "OVR_CAPI_0_5_0.h" +#include "OVR_CAPI.h" class GuiCanvas; class GameConnection; struct DisplayPose; class OculusVRSensorDevice; +struct OculusTexture; + class OculusVRHMDDevice { @@ -59,9 +61,6 @@ protected: ovrHmd mDevice; - U32 mSupportedDistortionCaps; - U32 mCurrentDistortionCaps; - U32 mSupportedCaps; U32 mCurrentCaps; @@ -70,15 +69,12 @@ protected: String mManufacturer; U32 mVersion; - // Windows display device name used in EnumDisplaySettings/CreateDC - String mDisplayDeviceName; + // Device type (D3D11, etc) + String mDisplayDeviceType; - // MacOS display ID + // Adapter index S32 mDisplayId; - // Desktop coordinate position of the screen (can be negative; may not be present on all platforms) - Point2I mDesktopPosition; - // Whole screen resolution Point2I mResolution; @@ -99,18 +95,15 @@ protected: Point2F mProjectionCenterOffset; // Current pose of eyes - ovrPosef mCurrentEyePoses[2]; ovrEyeRenderDesc mEyeRenderDesc[2]; - ovrFovPort mCurrentFovPorts[2]; - - Point2I mWindowSize; - GameConnection *mConnection; OculusVRSensorDevice *mSensor; U32 mActionCodeIndex; + ovrGraphicsLuid mLuid; + protected: void updateRenderInfo(); @@ -121,7 +114,7 @@ public: void cleanUp(); // Set the HMD properties based on information from the OVR device - void set(ovrHmd hmd, U32 actionCodeIndex); + void set(ovrHmd hmd, ovrGraphicsLuid luid, U32 actionCodeIndex); // Sets optimal display size for canvas void setOptimalDisplaySize(GuiCanvas *canvas); @@ -133,14 +126,11 @@ public: U32 getVersion() const { return mVersion; } // Windows display device name used in EnumDisplaySettings/CreateDC - const char* getDisplayDeviceName() const { return mDisplayDeviceName.c_str(); } + const char* getDisplayDeviceType () const { return mDisplayDeviceType.c_str(); } // MacOS display ID S32 getDisplayDeviceId() const { return mDisplayId; } - // Desktop coordinate position of the screen (can be negative; may not be present on all platforms) - const Point2I& getDesktopPosition() const { return mDesktopPosition; } - // Whole screen resolution const Point2I& getResolution() const { return mResolution; } @@ -166,7 +156,7 @@ public: void getStereoViewports(RectI *dest) const { dMemcpy(dest, mEyeViewport, sizeof(mEyeViewport)); } void getStereoTargets(GFXTextureTarget **dest) const { dest[0] = mEyeRT[0]; dest[1] = mEyeRT[1]; } - void getFovPorts(FovPort *dest) const { dMemcpy(dest, mCurrentFovPorts, sizeof(mCurrentFovPorts)); } + void getFovPorts(FovPort *dest) const { dMemcpy(dest, &mRenderLayer.Fov[0], sizeof(mRenderLayer.Fov)); } /// Returns eye offsets in torque coordinate space, i.e. z being up, x being left-right, and y being depth (forward). void getEyeOffsets(Point3F *offsets) const { @@ -181,7 +171,7 @@ public: void onEndFrame(); void onDeviceDestroy(); - Point2I generateRenderTarget(GFXTextureTargetRef &target, GFXTexHandle &texture, GFXTexHandle &depth, Point2I desiredSize); + Point2I generateRenderTarget(GFXTextureTargetRef &target, GFXTexHandle &depth, Point2I desiredSize); void clearRenderTargets(); bool isDisplayingWarning(); @@ -198,20 +188,12 @@ public: String dumpMetrics(); // Stereo RT - GFXTexHandle mStereoTexture; + GFXTexHandle mDebugStereoTexture; GFXTexHandle mStereoDepthTexture; GFXTextureTargetRef mStereoRT; // Eye RTs (if we are using separate targets) GFXTextureTargetRef mEyeRT[2]; - GFXTexHandle mEyeTexture[2]; - GFXTexHandle mEyeDepthTexture[2]; - - // Current render target size for each eye - Point2I mEyeRenderSize[2]; - - // Recommended eye target size for each eye - ovrSizei mRecomendedEyeTargetSize[2]; // Desired viewport for each eye RectI mEyeViewport[2]; @@ -220,6 +202,12 @@ public: F32 smDesiredPixelDensity; ovrTrackingState mLastTrackingState; + OculusTexture* mTextureSwapSet; + ovrLayerEyeFov mRenderLayer; + ovrLayerDirect mDebugRenderLayer; + ovrViewScaleDesc mScaleDesc; + ovrTexture* mDebugMirrorTexture; + GFXTexHandle mDebugMirrorTextureHandle; GFXDevice::GFXDeviceRenderStyles mDesiredRenderingMode; diff --git a/Engine/source/platform/input/oculusVR/oculusVRSensorData.h b/Engine/source/platform/input/oculusVR/oculusVRSensorData.h index 36436ab45..739751465 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRSensorData.h +++ b/Engine/source/platform/input/oculusVR/oculusVRSensorData.h @@ -27,7 +27,7 @@ #include "math/mMatrix.h" #include "math/mQuat.h" #include "math/mPoint2.h" -#include "OVR_CAPI_0_5_0.h" +#include "OVR_CAPI_0_8_0.h" struct OculusVRSensorData { diff --git a/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.cpp b/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.cpp index 47ad51770..cfdaa5be1 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.cpp +++ b/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.cpp @@ -24,8 +24,9 @@ #include "platform/input/oculusVR/oculusVRSensorData.h" #include "platform/input/oculusVR/oculusVRUtil.h" #include "platform/platformInput.h" -#include"console/simBase.h" +#include "console/simBase.h" #include "console/engineAPI.h" +#include "OVR_CAPI_0_8_0.h" U32 OculusVRSensorDevice::OVR_SENSORROT[OculusVRConstants::MaxSensors] = {0}; U32 OculusVRSensorDevice::OVR_SENSORROTANG[OculusVRConstants::MaxSensors] = {0}; @@ -66,7 +67,7 @@ void OculusVRSensorDevice::cleanUp() { mIsValid = false; - ovrHmd_ConfigureTracking(mDevice, 0, 0); + ovr_ConfigureTracking(mDevice, 0, 0); } void OculusVRSensorDevice::set(ovrHmd sensor, S32 actionCodeIndex) @@ -74,7 +75,7 @@ void OculusVRSensorDevice::set(ovrHmd sensor, S32 actionCodeIndex) mIsValid = false; mDevice = sensor; - mSupportedTrackingCaps = sensor->TrackingCaps; + mSupportedTrackingCaps = ovr_GetTrackingCaps(sensor); mCurrentTrackingCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position; mCurrentTrackingCaps = mSupportedTrackingCaps & mCurrentTrackingCaps; @@ -82,15 +83,17 @@ void OculusVRSensorDevice::set(ovrHmd sensor, S32 actionCodeIndex) mPositionTrackingDisabled = !(mCurrentTrackingCaps & ovrTrackingCap_Position); + ovrHmdDesc desc = ovr_GetHmdDesc(sensor); + // DeviceInfo - mProductName = sensor->ProductName; - mManufacturer = sensor->Manufacturer; - mVersion = sensor->Type; + mProductName = desc.ProductName; + mManufacturer = desc.Manufacturer; + mVersion = desc.Type; // SensorInfo - mVendorId = sensor->VendorId; - mProductId = sensor->ProductId; - mSerialNumber = sensor->SerialNumber; + mVendorId = desc.VendorId; + mProductId = desc.ProductId; + mSerialNumber = desc.SerialNumber; mActionCodeIndex = actionCodeIndex; @@ -163,7 +166,7 @@ bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bo return false; // Grab current state - ovrTrackingState ts = ovrHmd_GetTrackingState(mDevice, ovr_GetTimeInSeconds()); + ovrTrackingState ts = ovr_GetTrackingState(mDevice, ovr_GetTimeInSeconds(), ovrTrue); mLastStatus = ts.StatusFlags; // Store the current data from the sensor and compare with previous data @@ -249,7 +252,7 @@ void OculusVRSensorDevice::reset() if(!mIsValid) return; - ovrHmd_RecenterPose(mDevice); + ovr_RecenterPose(mDevice); } bool OculusVRSensorDevice::getYawCorrection() const @@ -322,7 +325,7 @@ EulerF OculusVRSensorDevice::getEulerRotation() if(!mIsValid) return Point3F::Zero; - ovrTrackingState ts = ovrHmd_GetTrackingState(mDevice, ovr_GetTimeInSeconds()); + ovrTrackingState ts = ovr_GetTrackingState(mDevice, ovr_GetTimeInSeconds(), ovrTrue); OVR::Quatf orientation = ts.HeadPose.ThePose.Orientation; // Sensor rotation in Euler format @@ -337,7 +340,7 @@ EulerF OculusVRSensorDevice::getRawEulerRotation() if(!mIsValid) return Point3F::Zero; - ovrTrackingState ts = ovrHmd_GetTrackingState(mDevice, ovr_GetTimeInSeconds()); + ovrTrackingState ts = ovr_GetTrackingState(mDevice, ovr_GetTimeInSeconds(), ovrTrue); OVR::Quatf orientation = ts.HeadPose.ThePose.Orientation; // Sensor rotation in Euler format @@ -351,7 +354,7 @@ VectorF OculusVRSensorDevice::getAcceleration() if(!mIsValid) return VectorF::Zero; - ovrTrackingState ts = ovrHmd_GetTrackingState(mDevice, ovr_GetTimeInSeconds()); + ovrTrackingState ts = ovr_GetTrackingState(mDevice, ovr_GetTimeInSeconds(), ovrTrue); OVR::Vector3f a = ts.HeadPose.LinearAcceleration; // Sensor acceleration in VectorF format @@ -366,7 +369,7 @@ EulerF OculusVRSensorDevice::getAngularVelocity() if(!mIsValid) return EulerF::Zero; - ovrTrackingState ts = ovrHmd_GetTrackingState(mDevice, ovr_GetTimeInSeconds()); + ovrTrackingState ts = ovr_GetTrackingState(mDevice, ovr_GetTimeInSeconds(), ovrTrue); OVR::Vector3f v = ts.HeadPose.AngularVelocity; // Sensor angular velocity in EulerF format @@ -381,7 +384,7 @@ Point3F OculusVRSensorDevice::getPosition() if(!mIsValid) return Point3F(); - ovrTrackingState ts = ovrHmd_GetTrackingState(mDevice, ovr_GetTimeInSeconds()); + ovrTrackingState ts = ovr_GetTrackingState(mDevice, ovr_GetTimeInSeconds(), ovrTrue); OVR::Vector3f v = ts.HeadPose.ThePose.Position; return Point3F(-v.x, v.z, -v.y); } @@ -399,5 +402,5 @@ void OculusVRSensorDevice::updateTrackingCaps() if (!mPositionTrackingDisabled) mCurrentTrackingCaps |= ovrTrackingCap_Position; - ovrHmd_ConfigureTracking(mDevice, mCurrentTrackingCaps, 0); + ovr_ConfigureTracking(mDevice, mCurrentTrackingCaps, 0); } diff --git a/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.h b/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.h index 418a9e28f..4c3cb6ccd 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.h +++ b/Engine/source/platform/input/oculusVR/oculusVRSensorDevice.h @@ -30,7 +30,7 @@ #include "math/mPoint4.h" #include "platform/input/oculusVR/oculusVRConstants.h" #include "platform/types.h" -#include "OVR_CAPI_0_5_0.h" +#include "OVR_CAPI.h" struct OculusVRSensorData; diff --git a/Engine/source/platform/input/oculusVR/oculusVRUtil.h b/Engine/source/platform/input/oculusVR/oculusVRUtil.h index 389af9da5..8056bb3c8 100644 --- a/Engine/source/platform/input/oculusVR/oculusVRUtil.h +++ b/Engine/source/platform/input/oculusVR/oculusVRUtil.h @@ -25,7 +25,7 @@ #include "math/mPoint2.h" #include "math/mMatrix.h" -#include "OVR_CAPI_0_5_0.h" +#include "OVR_CAPI_0_8_0.h" // NOTE: math code in oculus uses "Offset" which is a preprocessor macro #define TorqueOffset Offset diff --git a/Engine/source/postFx/postEffect.cpp b/Engine/source/postFx/postEffect.cpp index c388e0abe..7e4a6fed8 100644 --- a/Engine/source/postFx/postEffect.cpp +++ b/Engine/source/postFx/postEffect.cpp @@ -154,7 +154,6 @@ GFX_ImplementTextureProfile( VRTextureProfile, GFX_ImplementTextureProfile( VRDepthProfile, GFXTextureProfile::DiffuseMap, GFXTextureProfile::PreserveSize | - GFXTextureProfile::RenderTarget | GFXTextureProfile::NoMipmap | GFXTextureProfile::ZTarget, GFXTextureProfile::NONE ); diff --git a/Templates/Full/game/scripts/client/default.bind.cs b/Templates/Full/game/scripts/client/default.bind.cs index 9dcbca96b..1af881a81 100644 --- a/Templates/Full/game/scripts/client/default.bind.cs +++ b/Templates/Full/game/scripts/client/default.bind.cs @@ -752,3 +752,21 @@ vehicleMap.bind( gamepad, btn_b, brake ); vehicleMap.bind( gamepad, btn_x, movebackward ); // bind exiting the vehicle to a button vehicleMap.bindCmd(gamepad, btn_y,"getout();",""); + + +// ---------------------------------------------------------------------------- +// Oculus Rift +// ---------------------------------------------------------------------------- + +function OVRSensorRotEuler(%pitch, %roll, %yaw) +{ + //echo("Sensor euler: " @ %pitch SPC %roll SPC %yaw); + $mvRotZ0 = %yaw; + $mvRotX0 = %pitch; + $mvRotY0 = %roll; +} + +$mvRotIsEuler0 = true; +$OculusVR::GenerateAngleAxisRotationEvents = false; +$OculusVR::GenerateEulerRotationEvents = true; +moveMap.bind( oculusvr, ovr_sensorrotang0, OVRSensorRotEuler );