/// <summary>
        /// Gets the description of the buffers in the TextureSwapChain
        /// </summary>
        /// <param name="textureSwapChainDescription">Returns the description of the specified chain.</param>
        /// <returns>Returns an ovrResult for which the return code is negative upon error. </returns>
        public OVRTypes.Result GetDescription(out OVRTypes.TextureSwapChainDesc textureSwapChainDescription)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("TextureSwapChain");
            }

            OVRTypes.TextureSwapChainDesc textureSwapChainDesc = new OVRTypes.TextureSwapChainDesc();

            OVRTypes.Result result = OVR.GetTextureSwapChainDesc(Session, TextureSwapChainPtr, ref textureSwapChainDesc);
            textureSwapChainDescription = textureSwapChainDesc;

            return(result);
        }
示例#2
0
        /// <summary>
        /// Creates a TextureSwapChainDesc, based on a specified SharpDX texture description.
        /// </summary>
        /// <param name="texture2DDescription">SharpDX texture description.</param>
        /// <returns>TextureSwapChainDesc, based on the SharpDX texture description.</returns>
        public static OVRTypes.TextureSwapChainDesc CreateTextureSwapChainDescription(Texture2DDescription texture2DDescription)
        {
            OVRTypes.TextureSwapChainDesc textureSwapChainDescription = new OVRTypes.TextureSwapChainDesc();
            textureSwapChainDescription.Type        = OVRTypes.TextureType.Texture2D;
            textureSwapChainDescription.Format      = GetTextureFormat(texture2DDescription.Format);
            textureSwapChainDescription.ArraySize   = (int)texture2DDescription.ArraySize;
            textureSwapChainDescription.Width       = (int)texture2DDescription.Width;
            textureSwapChainDescription.Height      = (int)texture2DDescription.Height;
            textureSwapChainDescription.MipLevels   = (int)texture2DDescription.MipLevels;
            textureSwapChainDescription.SampleCount = (int)texture2DDescription.SampleDescription.Count;
            textureSwapChainDescription.StaticImage = 0;
            textureSwapChainDescription.MiscFlags   = GetTextureMiscFlags(texture2DDescription, false);
            textureSwapChainDescription.BindFlags   = GetTextureBindFlags(texture2DDescription.BindFlags);

            return(textureSwapChainDescription);
        }
示例#3
0
        /// <summary>
        /// Create VR swap texture set
        /// </summary>
        /// <returns>The result creation vr texture swap</returns>
        private OVRTypes.Result CreateVRSwapTextureSet()
        {
            var renderTargetManager = this.adapter.Graphics.RenderTargetManager as RenderTargetManager;

            OVRTypes.Result result;
            this.recommendedTextureSize    = new OVRTypes.Sizei[2];
            this.recommendedTextureSize[0] = this.Hmd.GetFovTextureSize(OVRTypes.EyeType.Left, this.Hmd.DefaultEyeFov[0], 1);
            this.recommendedTextureSize[1] = this.Hmd.GetFovTextureSize(OVRTypes.EyeType.Right, this.Hmd.DefaultEyeFov[1], 1);

            int rtWidth  = this.recommendedTextureSize[0].Width + this.recommendedTextureSize[1].Width;
            int rtHeight = Math.Max(this.recommendedTextureSize[0].Height, this.recommendedTextureSize[1].Height);

            var eyeDepthTexture = renderTargetManager.CreateDepthTexture(rtWidth, rtHeight, this.msaaSampleCount);

            if (this.msaaSampleCount > 1)
            {
                // Create MSAA renderTarget
                this.msaaRenderTarget = renderTargetManager.CreateRenderTarget(rtWidth, rtHeight, PixelFormat.R8G8BA8_sRGB, this.msaaSampleCount);
                this.msaaRenderTarget.DepthTexture = eyeDepthTexture;
            }

            // Define a texture at the size recommended for the eye texture.
            OVRTypes.TextureSwapChainDesc eyeSwapTextureDescription = new OVRTypes.TextureSwapChainDesc()
            {
                Type        = OVRTypes.TextureType.Texture2D,
                Format      = OVRTypes.TextureFormat.R8G8B8A8_UNORM_SRGB,
                ArraySize   = 1,
                Width       = rtWidth,
                Height      = rtHeight,
                MipLevels   = 1,
                SampleCount = 1,
                StaticImage = 0,
                MiscFlags   = OVRTypes.TextureMiscFlags.None,
                BindFlags   = OVRTypes.TextureBindFlags.DX_RenderTarget
            };

            // Create a SwapTextureSet, which will contain the textures to render to, for the current eye.
            result = this.Hmd.CreateTextureSwapChainDX(this.device.NativePointer, eyeSwapTextureDescription, out this.eyeTextureSwapChain);
            OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create swap texture set.");

            // Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet.
            int textureCount = 0;

            this.eyeTextureSwapChain.GetLength(out textureCount);
            this.swapRenderTargets = new RenderTarget[textureCount];

            for (int textureIndex = 0; textureIndex < textureCount; textureIndex++)
            {
                // Retrieve the Direct3D texture contained in the Oculus TextureSwapChainBuffer.
                IntPtr swapChainTextureComPtr = IntPtr.Zero;
                this.eyeTextureSwapChain.GetBufferDX(textureIndex, this.textureInterfaceId, out swapChainTextureComPtr);

                this.swapRenderTargets[textureIndex] = renderTargetManager.CreateRenderTarget(swapChainTextureComPtr);
                if (this.msaaSampleCount == 1)
                {
                    this.swapRenderTargets[textureIndex].DepthTexture = eyeDepthTexture;
                }
            }

            return(result);
        }
示例#4
0
        override protected void Render()
        {
            Lock = true;

            using (Wrap oculus = new Wrap())
            {
                // Initialize the Oculus runtime.
                if (!oculus.Initialize(initializationParameters))
                {
                    throw new HeadsetError("Failed to initialize the Oculus runtime library.");
                }

                OVRTypes.GraphicsLuid graphicsLuid;

                // Create a set of layers to submit.
                EyeTexture[] eyeTextures = new EyeTexture[2];

                // Create a depth buffer, using the same width and height as the back buffer.
                Texture2DDescription depthBufferDescription = new Texture2DDescription()
                {
                    Format            = Format.D32_Float,
                    ArraySize         = 1,
                    MipLevels         = 1,
                    Width             = 1920,            // TODO: FIXME?
                    Height            = 1080,
                    SampleDescription = new SampleDescription(1, 0),
                    Usage             = ResourceUsage.Default,
                    BindFlags         = BindFlags.DepthStencil,
                    CpuAccessFlags    = CpuAccessFlags.None,
                    OptionFlags       = ResourceOptionFlags.None
                };

                // Define how the depth buffer will be used to filter out objects, based on their distance from the viewer.
                DepthStencilStateDescription depthStencilStateDescription = new DepthStencilStateDescription()
                {
                    IsDepthEnabled  = true,
                    DepthComparison = Comparison.Less,
                    DepthWriteMask  = DepthWriteMask.Zero
                };

                //#if DEBUG
                //				SharpDX.Configuration.EnableObjectTracking = true;
                //#endif


                using (Hmd hmd = oculus.Hmd_Create(out graphicsLuid))
                    // Create DirectX drawing device.
                    using (_device = new Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.BgraSupport, new SharpDX.Direct3D.FeatureLevel[] { SharpDX.Direct3D.FeatureLevel.Level_10_0 }))
                        // Create DirectX Graphics Interface factory, used to create the swap chain.
                        using (Factory factory = new Factory())
                            using (DeviceContext immediateContext = _device.ImmediateContext)
                                // Create the depth buffer.
                                using (Texture2D depthBuffer = new Texture2D(_device, depthBufferDescription))
                                    using (DepthStencilView depthStencilView = new DepthStencilView(_device, depthBuffer))
                                        using (DepthStencilState depthStencilState = new DepthStencilState(_device, depthStencilStateDescription))
                                            using (Layers layers = new Layers())
                                                using (_gd = SharpDX.Toolkit.Graphics.GraphicsDevice.New(_device))
                                                    using (vrui = new VRUI(_device, _gd))
                                                        using (customEffectL = GetCustomEffect(_gd))
                                                            using (customEffectR = GetCustomEffect(_gd))
                                                            //using (SharpDX.Toolkit.Graphics.GeometricPrimitive primitive = GraphicTools.CreateGeometry(_projection, _gd, false))
                                                            {
                                                                if (hmd == null)
                                                                {
                                                                    throw new HeadsetError("Oculus Rift not detected.");
                                                                }
                                                                if (hmd.ProductName == string.Empty)
                                                                {
                                                                    throw new HeadsetError("The HMD is not enabled.");
                                                                }

                                                                Viewport    viewport    = new Viewport(0, 0, hmd.Resolution.Width, hmd.Resolution.Height, 0.0f, 1.0f);
                                                                LayerEyeFov layerEyeFov = layers.AddLayerEyeFov();

                                                                // Retrieve the DXGI device, in order to set the maximum frame latency.
                                                                using (SharpDX.DXGI.Device1 dxgiDevice = _device.QueryInterface <SharpDX.DXGI.Device1>())
                                                                {
                                                                    dxgiDevice.MaximumFrameLatency = 1;
                                                                }

                                                                for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++)
                                                                {
                                                                    OVRTypes.EyeType eye         = (OVRTypes.EyeType)eyeIndex;
                                                                    var        textureSize       = hmd.GetFovTextureSize(eye, hmd.DefaultEyeFov[eyeIndex], 1.0f);
                                                                    var        renderDescription = hmd.GetRenderDesc(eye, hmd.DefaultEyeFov[eyeIndex]);
                                                                    EyeTexture eyeTexture        = eyeTextures[eyeIndex] = new EyeTexture()
                                                                    {
                                                                        // Retrieve size and position of the texture for the current eye.
                                                                        FieldOfView       = hmd.DefaultEyeFov[eyeIndex],
                                                                        TextureSize       = textureSize,
                                                                        RenderDescription = renderDescription,
                                                                        // Define a texture at the size recommended for the eye texture.
                                                                        Viewport             = new Viewport(0, 0, textureSize.Width, textureSize.Height, 0.0f, 1.0f),
                                                                        HmdToEyeViewOffset   = renderDescription.HmdToEyeOffset,
                                                                        Texture2DDescription = new Texture2DDescription()
                                                                        {
                                                                            Width             = textureSize.Width,
                                                                            Height            = textureSize.Height,
                                                                            ArraySize         = 1,
                                                                            MipLevels         = 1,
                                                                            Format            = Format.R8G8B8A8_UNorm_SRgb,
                                                                            SampleDescription = new SampleDescription(1, 0),
                                                                            Usage             = ResourceUsage.Default,
                                                                            CpuAccessFlags    = CpuAccessFlags.None,
                                                                            BindFlags         = BindFlags.ShaderResource | BindFlags.RenderTarget
                                                                        }
                                                                    };
                                                                    eyeTexture.ViewportSize.Position = new OVRTypes.Vector2i(0, 0);
                                                                    eyeTexture.ViewportSize.Size     = textureSize;


                                                                    // Convert the SharpDX texture description to the native Direct3D texture description.
                                                                    OVRTypes.TextureSwapChainDesc textureSwapChainDesc = SharpDXHelpers.CreateTextureSwapChainDescription(eyeTexture.Texture2DDescription);

                                                                    AssertSuccess(hmd.CreateTextureSwapChainDX(_device.NativePointer, textureSwapChainDesc, out eyeTexture.SwapTextureSet),
                                                                                  oculus, "Failed to create swap chain.");

                                                                    // Retrieve the number of buffers of the created swap chain.
                                                                    int textureSwapChainBufferCount;
                                                                    AssertSuccess(eyeTexture.SwapTextureSet.GetLength(out textureSwapChainBufferCount),
                                                                                  oculus, "Failed to retrieve the number of buffers of the created swap chain.");


                                                                    // Create room for each DirectX texture in the SwapTextureSet.
                                                                    eyeTexture.Textures          = new Texture2D[textureSwapChainBufferCount];
                                                                    eyeTexture.RenderTargetViews = new RenderTargetView[textureSwapChainBufferCount];

                                                                    // Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet.
                                                                    for (int textureIndex = 0; textureIndex < textureSwapChainBufferCount; textureIndex++)
                                                                    {
                                                                        // Interface ID of the Direct3D Texture2D interface.
                                                                        Guid textureInterfaceId = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c");

                                                                        // Retrieve the Direct3D texture contained in the Oculus TextureSwapChainBuffer.
                                                                        IntPtr swapChainTextureComPtr = IntPtr.Zero;
                                                                        AssertSuccess(eyeTexture.SwapTextureSet.GetBufferDX(textureIndex, textureInterfaceId, out swapChainTextureComPtr),
                                                                                      oculus, "Failed to retrieve a texture from the created swap chain.");

                                                                        // Create a managed Texture2D, based on the unmanaged texture pointer.
                                                                        eyeTexture.Textures[textureIndex] = new Texture2D(swapChainTextureComPtr);

                                                                        // Create a render target view for the current Texture2D.
                                                                        eyeTexture.RenderTargetViews[textureIndex] = new RenderTargetView(_device, eyeTexture.Textures[textureIndex]);
                                                                    }

                                                                    // Define the depth buffer, at the size recommended for the eye texture.
                                                                    eyeTexture.DepthBufferDescription = new Texture2DDescription()
                                                                    {
                                                                        Format            = Format.D32_Float,
                                                                        Width             = eyeTexture.TextureSize.Width,
                                                                        Height            = eyeTexture.TextureSize.Height,
                                                                        ArraySize         = 1,
                                                                        MipLevels         = 1,
                                                                        SampleDescription = new SampleDescription(1, 0),
                                                                        Usage             = ResourceUsage.Default,
                                                                        BindFlags         = BindFlags.DepthStencil,
                                                                        CpuAccessFlags    = CpuAccessFlags.None,
                                                                        OptionFlags       = ResourceOptionFlags.None
                                                                    };

                                                                    // Create the depth buffer.
                                                                    eyeTexture.DepthBuffer      = new Texture2D(_device, eyeTexture.DepthBufferDescription);
                                                                    eyeTexture.DepthStencilView = new DepthStencilView(_device, eyeTexture.DepthBuffer);

                                                                    // Specify the texture to show on the HMD.
                                                                    layerEyeFov.ColorTexture[eyeIndex]      = eyeTexture.SwapTextureSet.TextureSwapChainPtr;
                                                                    layerEyeFov.Viewport[eyeIndex].Position = new OVRTypes.Vector2i(0, 0);
                                                                    layerEyeFov.Viewport[eyeIndex].Size     = eyeTexture.TextureSize;
                                                                    layerEyeFov.Fov[eyeIndex] = eyeTexture.FieldOfView;
                                                                    layerEyeFov.Header.Flags  = OVRTypes.LayerFlags.HighQuality;
                                                                }

                                                                #region Render loop
                                                                DateTime startTime = DateTime.Now;
                                                                DateTime lastTime  = DateTime.Now;
                                                                float    deltaTime = 0;

                                                                // Start with default background
                                                                SetDefaultScene();

                                                                while (!abort)
                                                                {
                                                                    UpdateContentIfRequested();

                                                                    OVRTypes.Vector3f[] hmdToEyeViewOffsets = { eyeTextures[0].HmdToEyeViewOffset, eyeTextures[1].HmdToEyeViewOffset };
                                                                    //OVR.FrameTiming frameTiming = hmd.GetFrameTiming(0);
                                                                    //OVR.TrackingState trackingState = hmd.GetTrackingState(frameTiming.DisplayMidpointSeconds);
                                                                    double displayMidpoint = hmd.GetPredictedDisplayTime(0);
                                                                    OVRTypes.TrackingState trackingState = hmd.GetTrackingState(displayMidpoint, true);
                                                                    OVRTypes.Posef[]       eyePoses      = new OVRTypes.Posef[2];

                                                                    // Calculate the position and orientation of each eye.
                                                                    oculus.CalcEyePoses(trackingState.HeadPose.ThePose, hmdToEyeViewOffsets, ref eyePoses);

                                                                    float timeSinceStart = (float)(DateTime.Now - startTime).TotalSeconds;
                                                                    deltaTime = (float)(DateTime.Now - lastTime).TotalSeconds;
                                                                    lastTime  = DateTime.Now;

                                                                    Vector3 centerEye = (eyePoses[0].Position.ToVector3() + eyePoses[1].Position.ToVector3()) * 0.5f;

                                                                    for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++)
                                                                    {
                                                                        OVRTypes.EyeType eye        = (OVRTypes.EyeType)eyeIndex;
                                                                        EyeTexture       eyeTexture = eyeTextures[eyeIndex];

                                                                        layerEyeFov.RenderPose[eyeIndex] = eyePoses[eyeIndex];

                                                                        // Update the render description at each frame, as the HmdToEyeOffset can change at runtime.
                                                                        eyeTexture.RenderDescription = hmd.GetRenderDesc(eye, hmd.DefaultEyeFov[eyeIndex]);

                                                                        // Retrieve the index of the active texture
                                                                        int textureIndex;
                                                                        AssertSuccess(eyeTexture.SwapTextureSet.GetCurrentIndex(out textureIndex),
                                                                                      oculus, "Failed to retrieve texture swap chain current index.");

                                                                        immediateContext.OutputMerger.SetRenderTargets(eyeTexture.DepthStencilView, eyeTexture.RenderTargetViews[textureIndex]);
                                                                        immediateContext.ClearRenderTargetView(eyeTexture.RenderTargetViews[textureIndex], Color.Black);
                                                                        immediateContext.ClearDepthStencilView(eyeTexture.DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);
                                                                        immediateContext.Rasterizer.SetViewport(eyeTexture.Viewport);



                                                                        // Retrieve the eye rotation quaternion and use it to calculate the LookAt direction and the LookUp direction.
                                                                        Quaternion lookRotation = SharpDXHelpers.ToQuaternion(eyePoses[eyeIndex].Orientation);
                                                                        lookRotation = new Quaternion(1, 0, 0, 0) * lookRotation;
                                                                        Matrix  rotationMatrix = Matrix.RotationQuaternion(lookRotation);
                                                                        Vector3 lookUp         = Vector3.Transform(new Vector3(0, -1, 0), rotationMatrix).ToVector3();
                                                                        Vector3 lookAt         = Vector3.Transform(new Vector3(0, 0, 1), rotationMatrix).ToVector3();

                                                                        //Vector3 eyeDiff = eyePoses[eyeIndex].Position.ToVector3() - eyePoses[1 - eyeIndex].Position.ToVector3();
                                                                        Vector3 lookPosition = new Vector3(
                                                                            -eyePoses[eyeIndex].Position.X,
                                                                            eyePoses[eyeIndex].Position.Y,
                                                                            eyePoses[eyeIndex].Position.Z
                                                                            );

                                                                        Matrix worldMatrix = Matrix.Translation(lookPosition);

                                                                        Matrix viewMatrix = Matrix.LookAtLH(lookPosition, lookPosition + lookAt, lookUp);

                                                                        Matrix projectionMatrix = oculus.Matrix4f_Projection(eyeTexture.FieldOfView, 0.1f, 100.0f, OVRTypes.ProjectionModifier.LeftHanded).ToMatrix();
                                                                        projectionMatrix.Transpose();

                                                                        Matrix MVP = worldMatrix * viewMatrix * projectionMatrix;
                                                                        customEffectL.Parameters["WorldViewProj"].SetValue(MVP);
                                                                        customEffectR.Parameters["WorldViewProj"].SetValue(MVP);

                                                                        lock (localCritical)
                                                                        {
                                                                            try
                                                                            {
                                                                                if (eyeIndex == 0)
                                                                                {
                                                                                    primitive?.Draw(customEffectL);
                                                                                }
                                                                                if (eyeIndex == 1)
                                                                                {
                                                                                    primitive?.Draw(customEffectR);
                                                                                }
                                                                            }
                                                                            catch (NullReferenceException)
                                                                            {
                                                                                ;
                                                                            }
                                                                        }

                                                                        if (ProvideLook != null && eyeIndex == 0)
                                                                        {
                                                                            lookRotation.Invert();
                                                                            lookRotation = lookRotation * new Quaternion(1, 0, 0, 0); // rotate 180 in x

                                                                            Vector3 forward = Vector3.Transform(Vector3.ForwardRH, lookRotation);
                                                                            Vector3 up      = Vector3.Transform(Vector3.Up, lookRotation);

                                                                            log.Publish("oculus.forward", forward.ToString("0.00"));
                                                                            log.Publish("oculus.up", up.ToString("0.00"));
                                                                            log.Publish("oculus.lookAt", lookAt.ToString("0.00"));
                                                                            log.Publish("oculus.lookUp", lookUp.ToString("0.00"));
                                                                            log.Publish("oculus.vr_quat", lookRotation);
                                                                            log.Publish("q.sent", lookRotation);

                                                                            ProvideLook(lookPosition, lookRotation, OculusFOV);
                                                                        }

                                                                        // reset UI position every frame if it is not visible
                                                                        if (vrui.isUIHidden)
                                                                        {
                                                                            vrui.SetWorldPosition(viewMatrix.Forward, lookPosition, false);
                                                                        }


                                                                        vrui.Draw(Media, currentTime, Duration);
                                                                        vrui.Render(deltaTime, viewMatrix, projectionMatrix, lookPosition, ShouldShowVRUI);

                                                                        // Commits any pending changes to the TextureSwapChain, and advances its current index
                                                                        AssertSuccess(eyeTexture.SwapTextureSet.Commit(), oculus, "Failed to commit the swap chain texture.");

                                                                        //Console.WriteLine("xbox: " + ((hmd.ovr_GetConnectedControllerTypes() & OVRTypes.ControllerType.XBox) != 0));
                                                                        //Console.WriteLine("remote: " + ((hmd.ovr_GetConnectedControllerTypes() & OVRTypes.ControllerType.Remote) != 0));
                                                                        //Console.WriteLine("active: " + hmd.GetInputState(OVRTypes.ControllerType.Active));
                                                                        //Console.WriteLine("buttons: " + hmd.GetInputState(OVRTypes.ControllerType.Remote).Buttons);
                                                                    }

                                                                    hmd.SubmitFrame(0, layers);
                                                                }

                                                                #endregion
                                                                //debugWindow.Stop();

                                                                waitForRendererStop.Set();

                                                                // Release all resources
                                                                primitive?.Dispose();
                                                                eyeTextures[0].Dispose();
                                                                eyeTextures[1].Dispose();
                                                                immediateContext.ClearState();
                                                                immediateContext.Flush();
                                                            }
            }

            Lock = false;
        }
        public TextureBuffer(Wrap oculus, Hmd hmd, bool rendertarget, bool displayableOnHmd, OVRTypes.Sizei size, int mipLevels, IntPtr data, int sampleCount)
        {
            wrap = oculus;
            texSize = size;

            OVRTypes.Result result;

            Debug.Assert(sampleCount <= 1); // The code doesn't currently handle MSAA textures.

            if (displayableOnHmd)
            {
                // This texture isn't necessarily going to be a rendertarget, but it usually is.
                Debug.Assert(hmd != null); // No HMD? A little odd.

                // It looks like that in order to disable sRGB we have to
                // set the texture format to sRGB but omit the call the
                // enabling sRGB in the framebuffer. Info here:
                // https://forums.oculus.com/community/discussion/24347/srgb-and-sdk-0-6-0-0

                OVRTypes.TextureSwapChainDesc desc = new OVRTypes.TextureSwapChainDesc();
                desc.Type = OVRTypes.TextureType.Texture2D;
                desc.ArraySize = 1;
                desc.Width = size.Width;
                desc.Height = size.Height;
                desc.MipLevels = mipLevels;
                desc.Format = OVRTypes.TextureFormat.R8G8B8A8_UNORM_SRGB; //Remember to call GL.Disable(EnableCap.FramebufferSrgb) later
                desc.SampleCount = sampleCount;
                desc.StaticImage = 0;
                if (mipLevels > 1)
                    desc.MiscFlags = OVRTypes.TextureMiscFlags.AllowGenerateMips;

                result = hmd.CreateTextureSwapChainGL(desc, out textureChain);
                WriteErrorDetails(wrap, result, "Failed to create swap chain.");

                int length = 0;
                result = TextureChain.GetLength(out length);
                WriteErrorDetails(wrap, result, "Failed to retrieve the number of buffers of the created swap chain.");

                if (result >= OVRTypes.Result.Success)
                {
                    for (int i = 0; i < length; ++i)
                    {
                        uint chainTexId;

                        // Retrieve the OpenGL texture contained in the Oculus TextureSwapChainBuffer.
                        result = TextureChain.GetBufferGL(i, out chainTexId);
                        WriteErrorDetails(wrap, result, "Failed to retrieve a texture from the created swap chain.");
                        GL.BindTexture(TextureTarget.Texture2D, chainTexId);

                        if (rendertarget)
                        {
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
                        }
                        else
                        {
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat);
                        }
                    }
                }
            }
            else
            {
                GL.GenTextures(1, out texId);
                GL.BindTexture(TextureTarget.Texture2D, texId);

                if (rendertarget)
                {
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
                }
                else
                {
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat);
                }

                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Srgb8Alpha8, texSize.Width, texSize.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
            }

            if (mipLevels > 1)
            {
                GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
            }

            GL.GenFramebuffers(1, out fboId);
        }