private void OnDestroy() { if (varjoCamera != null && cameraBlitCB != null && blitCBInjected) { varjoCamera.RemoveCommandBuffer(CameraEvent.AfterImageEffects, cameraBlitCB); blitCBInjected = false; } if (camRenderTextures != null) { foreach (var rt in camRenderTextures) { if (rt != null) { rt.Release(); Destroy(rt); } } } if (camSwapchains != null) { if (VarjoPlugin.SessionValid) { foreach (var swapchain in camSwapchains) { VarjoPlugin.QueueDestroySwapchain(swapchain); } VarjoManager.Instance.Plugin.IssuePluginEvent(VarjoPlugin.VARJO_RENDER_EVT_PROCESS_SWAPCHAINS); } } }
private static bool CheckError() { int error = VarjoPlugin.GetError(); if (error != 0) { Debug.LogWarning(VarjoPlugin.GetErrorMsg(error)); return(false); } return(true); }
IEnumerator InitializeSession() { Plugin.AttemptSessionInit(); // If we failed to initialize the session, attempt to initialize a valid session until we get one. if (!VarjoPlugin.SessionValid) { Debug.LogWarning("Failed to initialize a Varjo session. Entering into poll mode..."); EnableAllViewportCameras(false); while (!VarjoPlugin.SessionValid) { bool wait = true; Plugin.AttemptSessionInitThreaded(() => wait = false); while (wait) { yield return(new WaitForSecondsRealtime(0.5f)); } } EnableAllViewportCameras(true); } int viewCount = VarjoPlugin.GetViewCount(); if (viewCount != 4) { Debug.LogErrorFormat("Only 4 views are supported by this plugin, however Varjo Runtime reports {0} views", viewCount); EnableAllViewportCameras(false); while (true) { yield return(new WaitForSecondsRealtime(0.5f)); } } Debug.Log("Varjo session init successful"); StartCoroutine(EndFrameCoroutine()); }
private new void Awake() { unityThread = Thread.CurrentThread; if (_instance == null) { _instance = this; } else { Debug.LogError("Multiple instances of VarjoManager. Destroying the new one."); Destroy(gameObject); return; } Plugin = new VarjoPlugin(); VarjoSystemPresent = VarjoPlugin.IsVarjoSystemInstalled(); if (!VarjoSystemPresent) { Debug.LogWarning("Varjo system not found."); return; } base.Awake(); // Check that the varjoCamera is valid. if (varjoCamera == null) { varjoCamera = Camera.main; if (varjoCamera == null) { LogWarning("No camera attached to VarjoManager. Attach a camera or make sure there is main camera in the scene."); enabled = false; return; } } StartCoroutine(InitializeSession()); }
private bool VerifyCamera() { if (cam == null) { cam = GetComponent <Camera>(); } if (cam == null) { cam = gameObject.AddComponent <Camera>(); } if (m_Owner == null) { m_Owner = GetComponentInParent <VarjoLayer>(); } if (cam && m_Owner && m_Owner.useOcclusionMesh && (m_OcclusionMeshVerts == null)) { m_OcclusionMesh = null; m_OcclusionMeshVerts = VarjoPlugin.GetOcclusionMesh((int)CameraId); if (m_OcclusionMeshVerts.Length > 0) { m_OcclusionMesh = new Mesh(); int vertCount = m_OcclusionMeshVerts.Length / 2; var vertices = new Vector3[vertCount]; var indices = new int[vertices.Length]; for (int i = 0; i < vertices.Length; ++i) { vertices[i] = new Vector3(m_OcclusionMeshVerts[i * 2], m_OcclusionMeshVerts[i * 2 + 1], 0.0f); indices[i] = i; } m_OcclusionMesh.vertices = vertices; m_OcclusionMesh.triangles = indices; } } return(cam != null); }
// Retrieve the occlusion mesh, store it as a triangle list into a float[], with alternating x and y coordinates public static float[] GetOcclusionMesh(int viewIndex) { int vertCount = 0; IntPtr vertexData; var occMesh = CreateOcclusionMesh((int)viewIndex, out vertCount, out vertexData); if (occMesh != (IntPtr)0) { var res = new float[vertCount * 2]; if (vertCount > 0) { System.Runtime.InteropServices.Marshal.Copy(vertexData, res, 0, vertCount * 2); } VarjoPlugin.FreeOcclusionMesh(occMesh); return(res); } else { return(new float[0]); } }
private IEnumerator EndFrameCoroutine() { while (true) { yield return(yieldEndOfFrame); if (!VarjoPlugin.SessionValid || !beginFrameCalled) { Profiler.BeginSample("Varjo.EndOfFrame.ThrottleFor100ms"); // Sleep for 100ms so that we won't hog the CPU Thread.Sleep(100); // Still poll events if we have a session if (VarjoPlugin.SessionValid) { Plugin.IssuePluginEvent(VarjoPlugin.VARJO_RENDER_EVT_POLL_EVENTS); } GL.Flush(); Profiler.EndSample(); continue; } Profiler.BeginSample("Varjo.EndOfFrame"); if (VarjoManager.Instance.viewportCameras == null || VarjoManager.Instance.viewportCameras.Count != 4) { VarjoManager.LogError("VarjoViewCombiner can't access a proper viewport array."); continue; } GL.sRGBWrite = true; Profiler.BeginSample("Varjo.Submit"); submission.Clear(); // Sort the layers according to layer depth foreach (var varjoLayer in layers.OrderBy(l => l.layerOrder)) { if (varjoLayer.layerEnabled) { submission.Add(varjoLayer.PrepareForSubmission()); } } var subArray = submission.ToArray(); VarjoPlugin.QueueSubmission(subArray.Length, subArray); Profiler.EndSample(); // Blit to screen if SRPs are in use if (GraphicsSettings.renderPipelineAsset != null) { Profiler.BeginSample("Varjo.BlitToScreen"); // Blit left context of the main layer to screen if (flipY) { Graphics.Blit(GetRenderTextureForCamera(VarjoViewCamera.CAMERA_ID.CONTEXT_LEFT), (RenderTexture)null, new Vector2(contextDisplayFactor, contextDisplayFactor), new Vector2(0.0f, 1.0f - contextDisplayFactor)); } else { Graphics.Blit(GetRenderTextureForCamera(VarjoViewCamera.CAMERA_ID.CONTEXT_LEFT), (RenderTexture)null, new Vector2(contextDisplayFactor, -1.0f * contextDisplayFactor), new Vector2(0.0f, contextDisplayFactor)); } Profiler.EndSample(); } Plugin.IssuePluginEvent(VarjoPlugin.VARJO_RENDER_EVT_SUBMIT); GL.InvalidateState(); beginFrameCalled = false; Profiler.EndSample(); } }
private void Update() { // Empty the lock message queue lock (logMessages) { while (logMessages.Count > 0) { var txt = logMessages.Dequeue(); if (debug) { Debug.Log(txt); } } } if (!VarjoPlugin.SessionValid) { return; } // Update events buttonEvents.Clear(); Profiler.BeginSample("Varjo.PollEvents"); while (VarjoPlugin.PollEvent(ref eventType)) { switch ((VarjoPlugin.EventType)eventType) { // Keep track of application visibility and standby status // and enable and disable rendering based on that case VarjoPlugin.EventType.EVENT_VISIBILITY: layerVisible = VarjoPlugin.GetEventVisibility().visible != 0; if (OnVisibilityEvent != null) { OnVisibilityEvent(layerVisible); } break; case VarjoPlugin.EventType.EVENT_HEADSET_STANDBY_STATUS: inStandBy = VarjoPlugin.GetEventHeadsetStandbyStatus().onStandby != 0; if (OnStandbyEvent != null) { OnStandbyEvent(inStandBy); } break; case VarjoPlugin.EventType.EVENT_FOREGROUND: if (OnForegroundEvent != null) { OnForegroundEvent(VarjoPlugin.GetEventForeground().isForeground != 0); } break; // Update headset button states case VarjoPlugin.EventType.EVENT_BUTTON: buttonEvents.Add(VarjoPlugin.GetEventButton()); break; case VarjoPlugin.EventType.EVENT_MR_DEVICE_STATUS: if (OnMRDeviceStatusEvent != null) { OnMRDeviceStatusEvent(VarjoPlugin.GetEventMRDeviceStatus().status == VarjoPlugin.MRDeviceStatus.Connected); } break; case VarjoPlugin.EventType.EVENT_MR_CAMERA_PROPERTY_CHANGE: if (OnMRCameraPropertyChangeEvent != null) { OnMRCameraPropertyChangeEvent(VarjoPlugin.GetEventMRCameraPropertyChange().type); } break; case VarjoPlugin.EventType.EVENT_DATA_STREAM_START: if (OnDataStreamStartEvent != null) { OnDataStreamStartEvent(VarjoPlugin.GetEventDataStreamStart().streamId); } break; case VarjoPlugin.EventType.EVENT_DATA_STREAM_STOP: if (OnDataStreamStopEvent != null) { OnDataStreamStopEvent(VarjoPlugin.GetEventDataStreamStop().streamId); } break; } } Profiler.EndSample(); // Call waitsync and sync the render thread if (layerVisible && !inStandBy) { Profiler.BeginSample("Varjo.WaitSync"); Plugin.IssuePluginEvent(VarjoPlugin.VARJO_RENDER_EVT_WAITSYNC); VarjoPlugin.SyncRenderThread(); Profiler.EndSample(); } // Fetch fresh pose data and cache it VarjoPlugin.GetFramePoseData(ref latestFramePose); // Update layers foreach (var layer in layers) { layer.UpdateFromManager(); } // Start rendering only if layer is visible if (layerVisible && !inStandBy) { if (!beginFrameCalled) { EnableAllViewportCameras(true); Plugin.IssuePluginEvent(VarjoPlugin.VARJO_RENDER_EVT_BEGIN_FRAME); beginFrameCalled = true; } } else { EnableAllViewportCameras(false); } }
private new void Awake() { unityThread = Thread.CurrentThread; if (_instance == null) { _instance = this; } else { Debug.LogError("Multiple instances of VarjoManager. Destroying the new one."); Destroy(gameObject); return; } Plugin = new VarjoPlugin(); VarjoSystemPresent = VarjoPlugin.IsVarjoSystemInstalled(); if (!VarjoSystemPresent) { Debug.LogWarning("Varjo system not found."); gameObject.SetActive(false); return; } if (forceVRSupport) { XRSettings.enabled = true; if (XRSettings.supportedDevices != null && XRSettings.supportedDevices.Contains("OpenVR")) { if (XRSettings.loadedDeviceName != "OpenVR") { XRSettings.LoadDeviceByName("OpenVR"); } } else { Debug.LogError("OpenVR is not in the list of supported Virtual Reality SDKs. You need to add it to the list in Player Settings."); } } else { if (!XRSettings.enabled) { Debug.LogError("Virtual Reality Support is not enabled. Enable Force VR Support in VarjoManager or enable Virtual Reality Support in Player Settings."); } } if (disableVSync) { QualitySettings.vSyncCount = 0; } base.Awake(); if (varjoCamera) { varjoCamera.gameObject.tag = "MainCamera"; } else { GameObject go = new GameObject("Varjo Camera"); go.transform.SetParent(transform); varjoCamera = go.AddComponent <Camera>(); go.tag = "MainCamera"; } DisableVRCameras(); DisableExtraAudioListeners(); StartCoroutine(InitializeSession()); }
/// <summary> /// Gets a render texture for a camera with correct dimensions and format. /// Creates a texture if it's not created. VarjoManager takes care of texture destruction. /// </summary> /// <param name="cameraId">Camera Id</param> /// <returns>Render texture</returns> public RenderTexture GetRenderTextureForCamera(VarjoViewCamera.CAMERA_ID cameraId) { Profiler.BeginSample("Varjo.GetRenderTextureForCamera"); if (!VarjoPlugin.SessionValid) { Debug.LogError("GetRenderTextureForCamera called without a valid session."); Profiler.EndSample(); return(null); } var texDesc = VarjoPlugin.GetRenderTextureFormat((int)cameraId); if (texDesc.width <= 0 || texDesc.height <= 0) { Debug.Log(string.Format("Invalid texture descriptor: {0}x{1} {2}", texDesc.width, texDesc.height, texDesc.format)); Profiler.EndSample(); return(null); } int camIndex = (int)cameraId; if (camRenderTextures[camIndex] != null) { Profiler.EndSample(); return(camRenderTextures[camIndex]); } // TODO: framebuffer dimensions can change per frame. Debug.Log(string.Format("Creating render target: {0}x{1}", texDesc.width, texDesc.height)); RenderTextureDescriptor rtd = new RenderTextureDescriptor() { width = texDesc.width, height = texDesc.height, colorFormat = ConvertPluginRenderTextureFormat(texDesc.format), depthBufferBits = 32, dimension = TextureDimension.Tex2D, volumeDepth = 1, msaaSamples = 1, // TODO: get the correct MSAA sRGB = true, }; camRenderTextures[camIndex] = new RenderTexture(rtd); camRenderTextures[camIndex].Create(); // Also create the swapchain var cfg = new VarjoPlugin.SwapchainConfig() { format = VarjoPlugin.varjo_TextureFormat_R8G8B8A8_SRGB, numberOfTextures = 4, textureWidth = texDesc.width, textureHeight = texDesc.height, arraySize = 1 }; camSwapchains[camIndex] = VarjoPlugin.CreateD3D11Swapchain(cfg); // And depth swapchain if requested if (submitDepth) { cfg.format = VarjoPlugin.varjo_DepthTextureFormat_D32_FLOAT; camDepthSwapchains[camIndex] = VarjoPlugin.CreateD3D11Swapchain(cfg); } // Hook up the texture directly to the view struct so that we don't have to call GetNativeTexturePtr() every frame var view = submitLayer.views[camIndex]; view.unityColorTex = camRenderTextures[camIndex].GetNativeTexturePtr(); if (submitDepth) { view.unityDepthTex = camRenderTextures[camIndex].GetNativeDepthBufferPtr(); } submitLayer.views[camIndex] = view; Profiler.EndSample(); return(camRenderTextures[camIndex]); }