/// <summary> /// Loads the resource. /// </summary> /// <param name="device">The target device.</param> /// <param name="resources">Parent ResourceDictionary.</param> protected override void LoadResourceInternal(EngineDevice device, ResourceDictionary resources) { //Get default resources m_defaultResources = resources.GetResourceAndEnsureLoaded( DefaultResources.RESOURCE_KEY, () => new DefaultResources()); }
/// <summary> /// Discards this RenderPass (called after rendering all objects of this pass). /// </summary> /// <param name="renderState">The current render state.</param> public override void Discard(RenderState renderState) { EngineDevice device = renderState.Device; device.DeviceImmediateContextD3D11.Rasterizer.State = m_defaultResources.RasterStateDefault; device.DeviceImmediateContextD3D11.InputAssembler.PrimitiveTopology = D3D.PrimitiveTopology.TriangleList; }
/// <summary> /// Initializes a new instance of the <see cref="Direct2DOverlayRenderer"/> class. /// </summary> internal Direct2DOverlayRenderer(EngineDevice device, D3D11.Texture2D renderTarget3D, int viewWidth, int viewHeight, DpiScaling dpiScaling, bool forceInit) { m_device = device; m_renderTarget3D = renderTarget3D; CreateResources(viewWidth, viewHeight, dpiScaling, forceInit); }
/// <summary> /// Initializes a new instance of the <see cref="RenderState"/> class. /// </summary> internal RenderState( EngineDevice device, PerformanceAnalyzer performanceCalculator, RenderTargets renderTargets, SharpDX.Mathematics.Interop.RawViewportF viewport, Camera3DBase camera, ViewInformation viewInformation) : this(device, performanceCalculator) { Reset(renderTargets, viewport, camera, viewInformation); }
/// <summary> /// Applies this RenderPass (called before starting rendering first objects with it). /// </summary> /// <param name="renderState">The current render state.</param> public override void Apply(RenderState renderState) { EngineDevice device = renderState.Device; device.DeviceImmediateContextD3D11.Rasterizer.State = m_defaultResources.RasterStateLines; device.DeviceImmediateContextD3D11.InputAssembler.PrimitiveTopology = D3D.PrimitiveTopology.LineList; device.DeviceImmediateContextD3D11.InputAssembler.InputLayout = m_lineRenderResources.InputLayout; device.DeviceImmediateContextD3D11.VertexShader.Set(m_lineRenderResources.VertexShader.VertexShader); device.DeviceImmediateContextD3D11.PixelShader.Set(m_lineRenderResources.PixelShader.PixelShader); }
/// <summary> /// Initializes a new instance of the <see cref="TextureUploader"/> class. /// </summary> /// <param name="device">The device on which the texture was created.</param> /// <param name="texture">The texture which is to be uploaded to system memory.</param> internal TextureUploader(EngineDevice device, D3D11.Texture2D texture) { var textureDesc = texture.Description; m_device = device; m_texture = texture; m_width = textureDesc.Width; m_height = textureDesc.Height; m_format = textureDesc.Format; m_isMultisampled = (textureDesc.SampleDescription.Count > 1) || (textureDesc.SampleDescription.Quality > 0); }
/// <summary> /// Queries for all devices in use by given RenderLoop objects. /// </summary> /// <param name="registeredRenderLoops">The render loops from which to get the devices.</param> /// <param name="devicesInUse">The collection to be modiefied.</param> private static void QueryForDevicesInUse(List <RenderLoop> registeredRenderLoops, List <EngineDevice> devicesInUse) { devicesInUse.Clear(); for (int loop = 0; loop < registeredRenderLoops.Count; loop++) { EngineDevice actDevice = registeredRenderLoops[loop].Device; if ((actDevice != null) && (!devicesInUse.Contains(actDevice))) { devicesInUse.Add(actDevice); } } }
/// <summary> /// Initializes a new instance of the <see cref="DeviceHandlerD3D11" /> class. /// </summary> /// <param name="core">The core.</param> /// <param name="engineDevice">The engine device.</param> internal DeviceHandlerD2D(GraphicsCore core, EngineDevice engineDevice) { try { bool doFallbackMethod = core.Force2DFallbackMethod || (core.FactoryD2D_2 == null); // Simulate exception if requested if (GraphicsCore.ThrowD2DInitDeviceError) { throw new SeeingSharpGraphicsException("Simulation Direct2D device init exception"); } // Do default method (Windows 8 and newer) if (!doFallbackMethod) { try { using (DXGI.Device dxgiDevice = engineDevice.DeviceD3D11_1.QueryInterface <DXGI.Device>()) { m_deviceD2D = new D2D.Device1(engineDevice.Core.FactoryD2D_2, dxgiDevice); m_deviceContextD2D = new SharpDX.Direct2D1.DeviceContext( m_deviceD2D, D2D.DeviceContextOptions.None); m_renderTarget = m_deviceContextD2D; } } catch (Exception) { doFallbackMethod = true; } } // Fallback method (on older windows platforms (< Windows 8)) if (doFallbackMethod) { m_renderTarget = null; m_deviceD2D = null; m_deviceContextD2D = null; m_dummyRenderTargetTexture = GraphicsHelper.CreateRenderTargetTextureDummy( engineDevice.DeviceD3D11_1, 32, 32); m_dummyDirect2DOverlay = new Direct2DOverlayRenderer( engineDevice, m_dummyRenderTargetTexture, 32, 32, DpiScaling.Default, forceInit: true); } } catch (Exception) { GraphicsHelper.SafeDispose(ref m_deviceContextD2D); GraphicsHelper.SafeDispose(ref m_deviceD2D); GraphicsHelper.SafeDispose(ref m_dummyDirect2DOverlay); GraphicsHelper.SafeDispose(ref m_dummyRenderTargetTexture); GraphicsHelper.SafeDispose(ref m_renderTarget); } }
/// <summary> /// Initializes a new instance of the <see cref="ResourceDictionary"/> class. /// </summary> internal ResourceDictionary(EngineDevice device) { m_device = device; this.DeviceIndex = m_device.DeviceIndex; m_lastRenderBlockID = -1; m_renderableResources = new List <IRenderableResource>(); m_renderableResourcesPublic = new ReadOnlyCollection <IRenderableResource>(m_renderableResources); m_resources = new Dictionary <NamedOrGenericKey, ResourceInfo>(); m_resourcesMarkedForUnloading = new ThreadSaveQueue <Resource>(); }
/// <summary> /// Initializes a new instance of the <see cref="RenderState"/> class. /// </summary> /// <param name="device">The device object.</param> /// <param name="performanceCalculator">The object used to calculate performance values</param> private RenderState(EngineDevice device, PerformanceAnalyzer performanceCalculator) { //Set device members m_device = device; this.DeviceIndex = device.DeviceIndex; //Initialize world matrix m_world = new Matrix4Stack(Matrix4x4.Identity); //Create settings stack m_renderSettingsStack = new Stack <RenderStackEntry>(); m_sceneStack = new Stack <Tuple <Core.Scene, ResourceDictionary> >(); m_perfomanceCalculator = performanceCalculator; }
/// <summary> /// Registers the given view on this scene object. /// This method is meant to be called by RenderLoop class. /// </summary> /// <param name="viewInformation">The view to register.</param> internal void RegisterView(ViewInformation viewInformation) { viewInformation.EnsureNotNull(nameof(viewInformation)); bool isFirstView = m_registeredViews.Count == 0; InitializeResourceDictionaries(true); // Register device on this scene if not done before // -> This registration is forever, no deregister is made! EngineDevice givenDevice = viewInformation.Device; if (!m_registeredResourceDicts.HasObjectAt(givenDevice.DeviceIndex)) { throw new SeeingSharpGraphicsException("ResourceDictionary of device " + givenDevice.AdapterDescription + " not loaded in this scene!"); } // Check for already done registration of this view // If there is any, then caller made an error if (m_registeredViews.Contains(viewInformation)) { throw new SeeingSharpGraphicsException("The given view is already registered on this scene!"); } // Register this view on this scene and on all layers int viewIndex = m_registeredViews.AddObject(viewInformation); foreach (SceneLayer actLayer in m_sceneLayers) { actLayer.RegisterView(viewIndex, viewInformation, m_registeredResourceDicts[givenDevice.DeviceIndex]); } viewInformation.ViewIndex = viewIndex; // Mark this scene for deletion if we don't have any other view registered if (isFirstView) { GraphicsCore.Current.MainLoop.DeregisterSceneForUnload(this); } }
/// <summary> /// Initializes a new instance of the <see cref="ViewRelatedSceneLayerSubset" /> class. /// </summary> internal ViewRelatedSceneLayerSubset(SceneLayer sceneLayer, ViewInformation viewInformation, ResourceDictionary resources, int viewIndex) { m_scene = sceneLayer.Scene; m_sceneLayer = sceneLayer; m_viewInformation = viewInformation; m_device = ViewInformation.Device; m_resources = resources; ViewIndex = viewIndex; m_invalidObjects = new Dictionary <SceneObject, object>(); m_invalidObjectsToDeregister = new Queue <SceneObject>(); // Create temporary collections m_tmpChangedVisibilities = new List <Tuple <SceneObject, bool, bool> >(); // Create all specialized render pass lists m_objectsPassPlainRender = new PassSubscribionProperties(); m_objectsPassLineRender = new PassSubscribionProperties(); m_objectsPassTransparentRender = new PassSubscribionProperties(); m_objectsPassSpriteBatchRender = new PassSubscribionProperties(); m_objectsPass2DOverlay = new PassSubscribionProperties(); // Create dictionary for fast access to all render pass list m_objectsPerPassDict = new Dictionary <RenderPassInfo, PassSubscribionProperties>(); m_objectsPerPassDict[RenderPassInfo.PASS_PLAIN_RENDER] = m_objectsPassPlainRender; m_objectsPerPassDict[RenderPassInfo.PASS_LINE_RENDER] = m_objectsPassLineRender; m_objectsPerPassDict[RenderPassInfo.PASS_TRANSPARENT_RENDER] = m_objectsPassTransparentRender; m_objectsPerPassDict[RenderPassInfo.PASS_SPRITE_BATCH] = m_objectsPassSpriteBatchRender; m_objectsPerPassDict[RenderPassInfo.PASS_2D_OVERLAY] = m_objectsPass2DOverlay; m_objectsPerPass = new List <PassSubscribionProperties>(m_objectsPerPassDict.Values); m_anythingUnsubscribed = false; // Create and load all render pass relevant resources RefreshDeviceDependentResources(); }
/// <summary> /// Loads all resources of the object. /// </summary> /// <param name="device">Current graphics device.</param> /// <param name="resourceDictionary">Current resource dicionary.</param> public override void LoadResources(EngineDevice device, ResourceDictionary resourceDictionary) { }
/// <summary> /// Are resources loaded for the given device? /// </summary> /// <param name="device"></param> /// <returns></returns> public override bool IsLoaded(EngineDevice device) { return(true); }
/// <summary> /// Loads the resource. /// </summary> /// <param name="device">The target device.</param> /// <param name="resources">Parent ResourceDictionary.</param> protected override void LoadResourceInternal(EngineDevice device, ResourceDictionary resources) { m_defaultResources = resources.GetResourceAndEnsureLoaded <DefaultResources>(DefaultResources.RESOURCE_KEY); m_lineRenderResources = resources.GetResourceAndEnsureLoaded <LineRenderResources>(LineRenderResources.RESOURCE_KEY); }
/// <summary> /// Unloads the resource. /// </summary> /// <param name="device"></param> /// <param name="resources">Parent ResourceDictionary.</param> protected override void UnloadResourceInternal(EngineDevice device, ResourceDictionary resources) { }
public sealed override bool IsLoaded(EngineDevice device) { // No resources, so nothing to be done return(true); }
/// <summary> /// Unloads the resource. /// </summary> /// <param name="device">The target device.</param> /// <param name="resources">Parent ResourceDictionary.</param> protected override void UnloadResourceInternal(EngineDevice device, ResourceDictionary resources) { m_defaultResources = null; m_lineRenderResources = null; }
/// <summary> /// Updates the scene's and prepares all views for rendering. /// </summary> /// <param name="renderingRenderLoops">The registered render loops on the current pass.</param> /// <param name="scenesToRender">All scenes to be updated / rendered.</param> /// <param name="devicesInUse">The rendering devices that are in use.</param> /// <param name="inputFrames">All InputFrames gathered during last render.</param> /// <param name="updateState">Current global update state.</param> private async Task UpdateAndPrepareRendering(List <RenderLoop> renderingRenderLoops, List <Scene> scenesToRender, List <EngineDevice> devicesInUse, IEnumerable <InputFrame> inputFrames, UpdateState updateState) { using (var perfToken = m_host.BeginMeasureActivityDuration(Constants.PERF_GLOBAL_UPDATE_AND_PREPARE)) { List <Action> additionalContinuationActions = new List <Action>(); object additionalContinuationActionsLock = new object(); // Trigger all tasks for preparing views List <Task <List <Action> > > prepareRenderTasks = new List <Task <List <Action> > >(renderingRenderLoops.Count); for (int actDeviceIndex = 0; actDeviceIndex < devicesInUse.Count; actDeviceIndex++) { EngineDevice actDevice = devicesInUse[actDeviceIndex]; for (int loop = 0; loop < renderingRenderLoops.Count; loop++) { RenderLoop actRenderLoop = renderingRenderLoops[loop]; if (actRenderLoop.Device == actDevice) { // Call prepare render and wait for the answer // => Error handling is a bit tricky.. // Errors are catched by the continuation action var actTask = actRenderLoop.PrepareRenderAsync(); prepareRenderTasks.Add(actTask.ContinueWith((givenTask) => { if (!givenTask.IsFaulted) { return(givenTask.Result); } else { // Deregister this RenderLoop lock (additionalContinuationActionsLock) { additionalContinuationActions.Add(() => { this.DeregisterRenderLoop(actRenderLoop); renderingRenderLoops.Remove(actRenderLoop); }); } return(new List <Action>()); } })); } } } // Handle initial configuration of render loops (=> No current device) for (int loop = 0; loop < renderingRenderLoops.Count; loop++) { RenderLoop actRenderLoop = renderingRenderLoops[loop]; if (actRenderLoop.Device == null) { try { Task <List <Action> > actPrepareRenderTask = actRenderLoop.PrepareRenderAsync(); await actPrepareRenderTask; lock (additionalContinuationActionsLock) { additionalContinuationActions.AddRange(actPrepareRenderTask.Result); } } catch (Exception) { // Deregister this RenderLoop lock (additionalContinuationActionsLock) { additionalContinuationActions.Add(() => { this.DeregisterRenderLoop(actRenderLoop); renderingRenderLoops.Remove(actRenderLoop); }); } } } } // Update all scenes ThreadSaveQueue <Exception> exceptionsDuringUpdate = new ThreadSaveQueue <Exception>(); Parallel.For(0, scenesToRender.Count, (actTaskIndex) => { try { using (var perfToken2 = m_host.BeginMeasureActivityDuration( string.Format(Constants.PERF_GLOBAL_UPDATE_SCENE, actTaskIndex))) { Scene actScene = scenesToRender[actTaskIndex]; SceneRelatedUpdateState actUpdateState = actScene.CachedUpdateState; actUpdateState.OnStartSceneUpdate(actScene, updateState, inputFrames); actScene.Update(actUpdateState); } } catch (Exception ex) { exceptionsDuringUpdate.Enqueue(ex); } }); // Await synchronizations with the view(s) if (prepareRenderTasks.Count > 0) { await Task.WhenAll(prepareRenderTasks.ToArray()); } // Throw exceptions if any occurred during scene update // => This would be a fatal exception, so throw up to main loop if (exceptionsDuringUpdate.HasAny()) { throw new AggregateException("Error(s) during Scene update!", exceptionsDuringUpdate.DequeueAll().ToArray()); } // Trigger all continuation actions returned by the previously executed prepare tasks foreach (var actPrepareTasks in prepareRenderTasks) { if (actPrepareTasks.IsFaulted || actPrepareTasks.IsCanceled) { continue; } foreach (Action actContinuationAction in actPrepareTasks.Result) { actContinuationAction(); } } foreach (var actAction in additionalContinuationActions) { actAction(); } // Reset all dummy flags before rendering foreach (var actRenderLoop in renderingRenderLoops) { actRenderLoop.ResetFlagsBeforeRendering(); } // Unload all derigistered RenderLoops await UpdateRenderLoopRegistrationsAsync(renderingRenderLoops); } }
public sealed override void LoadResources(EngineDevice device, ResourceDictionary resourceDictionary) { // No resources, so nothing to be done }
/// <summary> /// Initializes a new instance of the <see cref="GraphicsCore"/> class. /// </summary> protected GraphicsCore(bool debugEnabled, bool force2DFallback) { try { // Upate RK.Common members m_debugEnabled = debugEnabled; m_force2DFallback = force2DFallback; m_devices = new List <EngineDevice>(); m_performanceCalculator = new PerformanceAnalyzer(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(2.0)); m_performanceCalculator.SyncContext = SynchronizationContext.Current; // <-- TODO m_performanceCalculator.RunAsync(CancellationToken.None) .FireAndForget(); m_configuration = new GraphicsCoreConfiguration(); m_configuration.DebugEnabled = debugEnabled; // Create container object for all input handlers m_inputHandlerFactory = new InputHandlerFactory(); m_importExporters = new ImporterExporterRepository(); // Create the key generator for resource keys m_resourceKeyGenerator = new UniqueGenericKeyGenerator(); // Try to initialize global api factories (mostly for 2D rendering / operations) try { if (s_throwDeviceInitError) { throw new SeeingSharpException("Simulated device initialization exception"); } m_factoryHandlerWIC = new FactoryHandlerWIC(); m_factoryHandlerD2D = new FactoryHandlerD2D(this); m_factoryHandlerDWrite = new FactoryHandlerDWrite(this); m_factoryHandlerXAudio2 = new FactoryHandlerXAudio2(); } catch (Exception ex) { m_initException = ex; m_devices.Clear(); m_factoryHandlerWIC = null; m_factoryHandlerD2D = null; m_factoryHandlerDWrite = null; m_factoryHandlerXAudio2 = null; return; } this.FactoryD2D = m_factoryHandlerD2D.Factory; this.FactoryD2D_2 = m_factoryHandlerD2D.Factory2; this.FactoryDWrite = m_factoryHandlerDWrite.Factory; this.FactoryWIC = m_factoryHandlerWIC.Factory; this.XAudioDevice = m_factoryHandlerXAudio2.Device; // Create the SoundManager m_soundManager = new SoundManager(m_factoryHandlerXAudio2); // Try to initialize Media Foundation interface // (This is a separated init step because MF may not be available on some systems, e. g. Servers) try { m_factoryHandlerMF = new FactoryHandlerMF(); } catch (Exception) { m_factoryHandlerMF = null; } // Create the object containing all hardware information m_hardwareInfo = new EngineHardwareInfo(); int actIndex = 0; foreach (var actAdapterInfo in m_hardwareInfo.Adapters) { EngineDevice actEngineDevice = new EngineDevice( this, m_configuration, actAdapterInfo.Adapter, actAdapterInfo.IsSoftwareAdapter, debugEnabled); if (actEngineDevice.IsLoadedSuccessfully) { actEngineDevice.DeviceIndex = actIndex; actIndex++; m_devices.Add(actEngineDevice); } } m_defaultDevice = m_devices.FirstOrDefault(); // Start input gathering m_inputGatherer = new InputGathererThread(); m_inputGatherer.Start(); // Start main loop m_mainLoop = new EngineMainLoop(this); if (m_devices.Count > 0) { m_mainLoopCancelTokenSource = new CancellationTokenSource(); m_mainLoopTask = m_mainLoop.Start(m_mainLoopCancelTokenSource.Token); } } catch (Exception ex2) { m_initException = ex2; m_hardwareInfo = null; m_devices.Clear(); m_configuration = null; m_resourceKeyGenerator = null; } }
/// <summary> /// Renders all given scenes using the different devices and performs "UpdateBesideRendering" step. /// </summary> /// <param name="registeredRenderLoops">The registered render loops on the current pass.</param> /// <param name="scenesToRender">All scenes to be updated / rendered.</param> /// <param name="devicesInUse">The rendering devices that are in use.</param> /// <param name="updateState">Current global update state.</param> private void RenderAndUpdateBeside( List <RenderLoop> registeredRenderLoops, List <Scene> scenesToRender, List <EngineDevice> devicesInUse, UpdateState updateState) { using (var perfToken = m_host.BeginMeasureActivityDuration(Constants.PERF_GLOBAL_RENDER_AND_UPDATE_BESIDE)) { ThreadSaveQueue <RenderLoop> invalidRenderLoops = new ThreadSaveQueue <RenderLoop>(); // Trigger all tasks for 'Update' pass Parallel.For(0, devicesInUse.Count + scenesToRender.Count, (actTaskIndex) => { if (actTaskIndex < devicesInUse.Count) { // Render all targets for the current device EngineDevice actDevice = devicesInUse[actTaskIndex]; using (var perfTokenInner = m_host.BeginMeasureActivityDuration(string.Format(Constants.PERF_GLOBAL_RENDER_DEVICE, actDevice.AdapterDescription))) { for (int loop = 0; loop < registeredRenderLoops.Count; loop++) { RenderLoop actRenderLoop = registeredRenderLoops[loop]; try { if (actRenderLoop.Device == actDevice) { actRenderLoop.Render(); } } catch (Exception) { // Mark this renderloop as invalid invalidRenderLoops.Enqueue(actRenderLoop); } } } } else { // Perform updates beside rendering for the current scene int sceneIndex = actTaskIndex - devicesInUse.Count; using (var perfTokenInner = m_host.BeginMeasureActivityDuration(string.Format(Constants.PERF_GLOBAL_UPDATE_BESIDE, sceneIndex))) { Scene actScene = scenesToRender[sceneIndex]; SceneRelatedUpdateState actUpdateState = actScene.CachedUpdateState; actUpdateState.OnStartSceneUpdate(actScene, updateState, null); actScene.UpdateBesideRender(actUpdateState); } } }); // Handle all invalid render loops if (invalidRenderLoops.HasAny()) { foreach (var actRenderLoop in invalidRenderLoops.DequeueAll()) { DeregisterRenderLoop(actRenderLoop); } } // Reset camera changed flags foreach (RenderLoop actRenderLoop in registeredRenderLoops) { actRenderLoop.Camera.StateChanged = false; } } }
/// <summary> /// Initializes a new instance of the <see cref="Direct2DOverlayRenderer"/> class. /// </summary> public Direct2DOverlayRenderer(EngineDevice device, D3D11.Texture2D renderTarget3D, int viewWidth, int viewHeight, DpiScaling dpiScaling) : this(device, renderTarget3D, viewWidth, viewHeight, dpiScaling, false) { }
/// <summary> /// Are resources loaded for the given device? /// </summary> public abstract bool IsLoaded(EngineDevice device);
/// <summary> /// Sets the default device to a hardware device. /// </summary> public void SetDefaultDeviceToHardware() { m_defaultDevice = m_devices.FirstOrDefault((actDevice) => actDevice.IsSoftware); }
/// <summary> /// Loads all resources of the object. /// </summary> /// <param name="device">Current graphics device.</param> /// <param name="resourceDictionary">Current resource dicionary.</param> public abstract void LoadResources(EngineDevice device, ResourceDictionary resourceDictionary);
/// <summary> /// Unloads all resources. /// </summary> /// <param name="device">The device on which the resources where loaded.</param> /// <param name="resources">The current ResourceDictionary.</param> protected abstract void UnloadResourceInternal(EngineDevice device, ResourceDictionary resources);