/// <summary> /// CreateResources is called when the VirtualRealityProvider is initialized and should create the DirectX resources. /// </summary> /// <remarks> /// <para> /// <b>CreateResources</b> is called when the VirtualRealityProvider is initialized and should create the DirectX resources. /// </para> /// <para> /// This method is called after this virtual reality provider is registered with calling the <see cref="DXScene.InitializeVirtualRealityRendering"/> method. /// This method then calls the <see cref="DXSceneResource.InitializeResources"/> and the <see cref="VirtualRealityProviderBase.OnInitializeResources"/>. /// OnInitializeResources calls the this CreateResources method and then <see cref="VirtualRealityProviderBase.InitializeRenderingSteps"/> method. /// </para> /// <para> /// This method usually creates pixel shaders and constant buffers. /// Other resources (back buffers and views) are usually created in <see cref="VirtualRealityProviderBase.UpdateRenderingContext"/> where the size of the current back buffer is compared with the size of back buffers for virtual reality. /// </para> /// </remarks> /// <param name="dxScene">parent DXScene</param> protected override void CreateResources(DXScene dxScene) { if (_eyeTextureSwapChains != null) { if (_eyeTextureSwapChains[0] != null) { _eyeTextureSwapChains[0].Dispose(); } if (_eyeTextureSwapChains[1] != null) { _eyeTextureSwapChains[1].Dispose(); } } else { _eyeTextureSwapChains = new OculusTextureSwapChain[2]; } _eyeTextureSwapChains[0] = new OculusTextureSwapChain(_ovr, _sessionPtr, dxScene.Device, EyeType.Left, Format.B8G8R8A8_UNorm_SRgb, _ovr.GetFovTextureSize(_sessionPtr, EyeType.Left, _hmdDesc.DefaultEyeFov[0], 1.0f), createDepthStencilView: true, isDebugDevice: dxScene.DXDevice.IsDebugDevice); _eyeTextureSwapChains[1] = new OculusTextureSwapChain(_ovr, _sessionPtr, dxScene.Device, EyeType.Left, Format.B8G8R8A8_UNorm_SRgb, _ovr.GetFovTextureSize(_sessionPtr, EyeType.Right, _hmdDesc.DefaultEyeFov[1], 1.0f), createDepthStencilView: true, isDebugDevice: dxScene.DXDevice.IsDebugDevice); _layerShared = new LayerEyeFov(); _layerShared.Header = new LayerHeader() { Type = LayerType.EyeFov, Flags = LayerFlags.HighQuality }; // Specify the texture to show on the HMD. _layerShared.ColorTextureLeft = _eyeTextureSwapChains[0].TextureSwapChainPtr; _layerShared.ColorTextureRight = _eyeTextureSwapChains[1].TextureSwapChainPtr; _layerShared.ViewportLeft.Position = new Vector2i(0, 0); _layerShared.ViewportLeft.Size = _eyeTextureSwapChains[0].Size; _layerShared.ViewportRight.Position = new Vector2i(0, 0); _layerShared.ViewportRight.Size = _eyeTextureSwapChains[1].Size; _layerShared.FovLeft = _hmdDesc.DefaultEyeFov[0]; _layerShared.FovRight = _hmdDesc.DefaultEyeFov[1]; _eyeRenderDesc[0] = _ovr.GetRenderDesc(_sessionPtr, EyeType.Left, _hmdDesc.DefaultEyeFov[0]); _hmdToEyeOffset[1] = _eyeRenderDesc[1].HmdToEyePose.Position; _eyeRenderDesc[1] = _ovr.GetRenderDesc(_sessionPtr, EyeType.Right, _hmdDesc.DefaultEyeFov[1]); _hmdToEyeOffset[1] = _eyeRenderDesc[1].HmdToEyePose.Position; // Create MSAA back buffer if needed UpdateMsaaBackBuffer(_eyeTextureSwapChains[0].Size.Width, _eyeTextureSwapChains[0].Size.Height, _multisamplingCount); _mirrorTextureDesc = new MirrorTextureDesc() { Format = SharpDXHelpers.GetTextureFormat(dxScene.BackBufferDescription.Format), Height = dxScene.BackBufferDescription.Height, MiscFlags = dxScene.BackBufferDescription.MipLevels != 1 ? TextureMiscFlags.AllowGenerateMips : TextureMiscFlags.None, Width = dxScene.BackBufferDescription.Width }; // FloorLevel will give tracking poses where the floor height is 0 _ovr.SetTrackingOriginType(_sessionPtr, TrackingOrigin.EyeLevel); IntPtr mirrorTexturePtr; var result = _ovr.CreateMirrorTextureDX(_sessionPtr, dxScene.Device.NativePointer, ref _mirrorTextureDesc, out mirrorTexturePtr); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Failed to create Oculus mirror texture: " + lastError.ErrorString, lastError.Result); } _mirrorTexture = new OculusMirrorTexture(_ovr, _sessionPtr, mirrorTexturePtr); // Retrieve the Direct3D texture contained in the Oculus MirrorTexture. IntPtr mirrorTextureComPtr; result = _mirrorTexture.GetBufferDX(typeof(Texture2D).GUID, out mirrorTextureComPtr); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Failed to retrieve the texture from the created mirror texture buffer: " + lastError.ErrorString, lastError.Result); } // Create a managed Texture2D, based on the unmanaged texture pointer. _mirrorTextureDX = new Texture2D(mirrorTextureComPtr); if (dxScene.DXDevice.IsDebugDevice) { _mirrorTextureDX.DebugName = "OculusMirrorTexture"; } // To prevent DirectX from rendering more then one frame in the background, // we need to set the MaximumFrameLatency to 1. // This prevents occasional dropped frames in Oculus Rift. var dxgiDevice = dxScene.Device.QueryInterface <SharpDX.DXGI.Device1>(); if (dxgiDevice != null) { dxgiDevice.MaximumFrameLatency = 1; dxgiDevice.Dispose(); } _frameIndex = 0; _matrixCamera = new MatrixCamera(); }
public OculusTextureSwapChain(OvrWrap ovr, IntPtr sessionPtr, SharpDX.Direct3D11.Device device, EyeType eye, Format format, Sizei size, bool createDepthStencilView = false, bool isDebugDevice = false) { _ovr = ovr; _sessionPtr = sessionPtr; _size = size; _viewportSize = size; _viewport = new ViewportF(0.0f, 0.0f, (float)size.Width, (float)size.Height); Format srgbFormat = GetSRgbFormat(format); TextureFormat textureFormat = SharpDXHelpers.GetTextureFormat(srgbFormat); TextureSwapChainDesc swapChainDesc = new TextureSwapChainDesc() { ArraySize = 1, BindFlags = TextureBindFlags.DX_RenderTarget, Format = textureFormat, Height = _size.Height, MipLevels = 1, MiscFlags = TextureMiscFlags.DX_Typeless, SampleCount = 1, Width = _size.Width }; Texture2DDescription description1 = new Texture2DDescription() { ArraySize = 1, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, Format = Format.R24G8_Typeless, Height = _size.Height, MipLevels = 1, OptionFlags = ResourceOptionFlags.None, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, Width = _size.Width }; ShaderResourceViewDescription description2 = new ShaderResourceViewDescription() { Format = srgbFormat, Dimension = ShaderResourceViewDimension.Texture2D }; description2.Texture2D.MipLevels = 1; // Create a texture swap chain, which will contain the textures to render to, for the current eye. var result = _ovr.CreateTextureSwapChainDX(_sessionPtr, device.NativePointer, ref swapChainDesc, out _textureSwapChainPtr); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Error creating Oculus TextureSwapChain: " + lastError.ErrorString, lastError.Result); } int length; result = _ovr.GetTextureSwapChainLength(_sessionPtr, _textureSwapChainPtr, out length); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Failed to retrieve the number of buffers of the created swap chain: " + lastError.ErrorString, lastError.Result); } _textures = new TextureItem[length]; for (int index = 0; index < length; ++index) { IntPtr bufferPtr; result = _ovr.GetTextureSwapChainBufferDX(_sessionPtr, _textureSwapChainPtr, index, typeof(Texture2D).GUID, out bufferPtr); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Failed to retrieve a texture from the created swap chain: " + lastError.ErrorString, lastError.Result); } Texture2D texture2D1 = new Texture2D(bufferPtr); Texture2D texture2D2 = null; DepthStencilView depthStencilView = null; if (createDepthStencilView) { texture2D2 = new Texture2D(device, description1); depthStencilView = new DepthStencilView(device, texture2D2, new DepthStencilViewDescription() { Flags = DepthStencilViewFlags.None, Dimension = DepthStencilViewDimension.Texture2D, Format = Format.D24_UNorm_S8_UInt }); } _textures[index] = new TextureItem() { Texture = texture2D1, TextureDescription = texture2D1.Description, DepthBuffer = texture2D2, DepthStencilView = depthStencilView, RTView = new RenderTargetView(device, texture2D1, new RenderTargetViewDescription() { Format = format, Dimension = RenderTargetViewDimension.Texture2D }), SRView = new ShaderResourceView(device, texture2D1, description2) }; if (isDebugDevice) { var eyeTextAndIndex = eye.ToString() + index.ToString(); _textures[index].Texture.DebugName = "OculusBackBuffer" + eyeTextAndIndex; _textures[index].RTView.DebugName = "OculusRT" + eyeTextAndIndex; _textures[index].SRView.DebugName = "OculusSR" + eyeTextAndIndex; _textures[index].DepthBuffer.DebugName = "OculusDepthBuffer" + eyeTextAndIndex; _textures[index].DepthStencilView.DebugName = "OculusDepthStencilView" + eyeTextAndIndex; } } }