Beispiel #1
0
        /// <summary>
        /// Prepares the render targets and pixel shader for rendering
        /// </summary>
        /// <param name="camera">A camera providing the transformation matrices</param>
        public void SetTargetsForRendering(Camera camera)
        {
            // update sun position and the displacement scale factor
            var data = new Vector4(Vector3.Normalize(new Vector3((float)Math.Sin(_sunx), (float)Math.Cos(_sunx), _suny)),
                                   TerrainEffectBase.DefaultScaleFactor);

            var device = _graphicsDeviceManager.GraphicsDevice;

            device.SetRenderTargets(device.DepthStencilBuffer, device.BackBuffer);

            device.Clear(SharpDX.Toolkit.Graphics.ClearOptions.DepthBuffer | SharpDX.Toolkit.Graphics.ClearOptions.Target, new Color4(0), 1f, 0);

            var context = _graphicsDeviceManager.GetContext2();

            context.Rasterizer.SetViewport(device.Viewport);

            _terrainRendererEffect.ColorTexture    = _diffuseTexture;
            _terrainRendererEffect.ColorResidency  = _diffuseResidency;
            _terrainRendererEffect.NormalTexture   = _normalTexture;
            _terrainRendererEffect.NormalResidency = _normalResidency;
            _terrainRendererEffect.SunPosition     = data;
        }
Beispiel #2
0
        /// <summary>
        /// Process all tile queues - loaded, unloaded, etc.
        /// </summary>
        public void ProcessQueues()
        {
            _seenTiles.Sort(TrackedTile.LoadComparison);
            _loadingTiles.Sort(TrackedTile.MapComparison);
            _mappedTiles.Sort(TrackedTile.EvictComparison);

            // schedule tiles for loading
            for (var i = _activeTileLoadingOperations; i < SampleSettings.TileResidency.MaxSimultaneousFileLoadTasks; i++)
            {
                // check if there is something to load
                if (_seenTiles.Count == 0)
                {
                    break;
                }

                var tileToLoad = _seenTiles[0];
                _seenTiles.Remove(tileToLoad); // remove the tile from the seen list

                Interlocked.Increment(ref _activeTileLoadingOperations);

                // schedule the tile for loading in a separate task
                tileToLoad.ManagedTiledResource
                .Loader
                .LoadTileAsync(tileToLoad.Coordinate)
                .ContinueWith(dataTask =>
                {
                    // store the loaded data and mark the tile as loaded
                    tileToLoad.TileData = dataTask.Result;
                    tileToLoad.State    = TileState.Loaded;
                    Interlocked.Decrement(ref _activeTileLoadingOperations);
                });

                _loadingTiles.Add(tileToLoad);
            }

            // holds all information about changed tiles that will need any updates on GPU
            var coalescedMapArguments = new Dictionary <SharpDX.Toolkit.Graphics.Texture2DBase, TileMappingUpdateArguments>();

            // process loaded tiles
            for (var i = 0; i < SampleSettings.TileResidency.MaxTilesLoadedPerFrame; i++)
            {
                if (_loadingTiles.Count == 0)
                {
                    break;
                }

                var tileToMap = _loadingTiles[0];

                // check if there are ready loaded tiles
                if (tileToMap.State != TileState.Loaded)
                {
                    break;
                }

                _loadingTiles.Remove(tileToMap);

                var physicalTileOffset = _reservedTiles + _mappedTiles.Count;

                // if there is no space for the new tile - need to find one to unload
                if (_mappedTiles.Count + _reservedTiles == SampleSettings.TileResidency.PoolSizeInTiles)
                {
                    var tileToEvict = _mappedTiles[0];

                    // if the tile that needs to be loaded is actually older than the tile to evict - keep the last one
                    if (tileToMap.lastSeen < tileToEvict.lastSeen)
                    {
                        _trackedTiles.Remove(new TileKey(tileToMap.Coordinate, tileToMap.ManagedTiledResource.Texture));

                        continue;
                    }

                    // untrack the evicted tile
                    _mappedTiles.Remove(tileToEvict);
                    _trackedTiles.Remove(new TileKey(tileToEvict.Coordinate, tileToEvict.ManagedTiledResource.Texture));

                    // store the index of the evicted tile
                    physicalTileOffset = tileToEvict.PhysicalTileOffset;

                    var argumentsForEvicted = GetOrCreate(coalescedMapArguments, tileToEvict.ManagedTiledResource.Texture);
                    argumentsForEvicted.Coordinates.Add(tileToEvict.Coordinate);
                    argumentsForEvicted.RangeFlags.Add(SharpDX.Direct3D11.TileRangeFlags.Null);
                    argumentsForEvicted.PhysicalOffsets.Add(physicalTileOffset);

                    // update the residency map for the evicted tile and decrease the loaded mip level for the current coordinate
                    UpdateResidencyMap(tileToEvict, false);
                }

                // store the offset in the tile pool
                tileToMap.PhysicalTileOffset = physicalTileOffset;
                tileToMap.State = TileState.Mapped;

                var argumentsForMapped = GetOrCreate(coalescedMapArguments, tileToMap.ManagedTiledResource.Texture);
                argumentsForMapped.Coordinates.Add(tileToMap.Coordinate);
                argumentsForMapped.RangeFlags.Add(0);
                argumentsForMapped.PhysicalOffsets.Add(physicalTileOffset);
                argumentsForMapped.TilesToMap.Add(tileToMap);

                // update the residency map with the information of the newly mapped tile and increase the mip level for the current coordinate
                UpdateResidencyMap(tileToMap, true);

                _mappedTiles.Add(tileToMap);
            }

            // get a reference to DirectX 11.2 device context
            var context = _graphicsDeviceManager.GetContext2();

            // for each managed resource ...
            foreach (var pair in coalescedMapArguments)
            {
                var arguments = pair.Value;
                var count     = arguments.RangeFlags.Count;

                var size = new SharpDX.Direct3D11.TileRegionSize {
                    TileCount = 1
                };
                // prepare the mapped regions array
                var rangeCounts = new int[count];
                Set(rangeCounts, 1);

                // prepare the mapped tile region size array
                var sizes = new SharpDX.Direct3D11.TileRegionSize[count];
                Set(sizes, size);

                // update tile mappings in a single call
                context.UpdateTileMappings(pair.Key,
                                           arguments.Coordinates.Count,
                                           arguments.Coordinates.ToArray(),
                                           sizes,
                                           _tilePool,
                                           count,
                                           arguments.RangeFlags.ToArray(),
                                           arguments.PhysicalOffsets.ToArray(),
                                           rangeCounts,
                                           0);

                context.TiledResourceBarrier(null, (SharpDX.Direct3D11.Resource)pair.Key);
            }

            // for each managed resource ...
            foreach (var pair in coalescedMapArguments)
            {
                var arguments = pair.Value;

                // ... for each tile coordinate ...
                for (var i = 0; i < arguments.Coordinates.Count; i++)
                {
                    // if the tile is present
                    if (arguments.RangeFlags[i] != SharpDX.Direct3D11.TileRangeFlags.Null)
                    {
                        var regionSize = new SharpDX.Direct3D11.TileRegionSize {
                            TileCount = 1
                        };
                        var tile = arguments.TilesToMap[0];

                        unsafe
                        {
                            fixed(void *pData = &tile.TileData[0])
                            {
                                // update the tile data from the provided byte array
                                context.UpdateTiles(pair.Key,
                                                    arguments.Coordinates[i],
                                                    regionSize,
                                                    new IntPtr(pData),
                                                    0);
                            }
                        }

                        tile.ManagedTiledResource.Loader.CompleteLoading(tile.TileData);

                        arguments.TilesToMap.Remove(tile);

                        tile.TileData = null;
                    }
                }
            }

            // update the residency textures
            foreach (var resource in _managedTiledResources)
            {
                var subresourceTiling = resource.SubresourceTilings[0];

                var baseMaxTileDimension = Math.Max(subresourceTiling.WidthInTiles, subresourceTiling.HeightInTiles);

                var bufferSize = baseMaxTileDimension * baseMaxTileDimension;
                if (_residencyBuffer == null || _residencyBuffer.Length < bufferSize)
                {
                    _residencyBuffer = new byte[bufferSize];
                }

                // update the data for each texture cube face
                for (var face = 0; face < 6; face++)
                {
                    for (var y = 0; y < baseMaxTileDimension; y++)
                    {
                        var tileY = (y * subresourceTiling.HeightInTiles) / baseMaxTileDimension;
                        for (var x = 0; x < baseMaxTileDimension; x++)
                        {
                            var tileX = (x * subresourceTiling.WidthInTiles) / baseMaxTileDimension;

                            _residencyBuffer[y * baseMaxTileDimension + x] = resource.Residency[face][tileY * subresourceTiling.WidthInTiles + tileX];
                        }
                    }

                    unsafe
                    {
                        fixed(void *pData = &_residencyBuffer[0])
                        context.UpdateSubresource(resource.ResidencyTexture, face, null, new IntPtr(pData), baseMaxTileDimension, 0);
                    }
                }
            }
        }