public ModelInstanceHandle CreateInstance(ModelHandle modelHandle, Material material, Transform initialTransform) { uint modelIndex = modelHandle.ModelIndex; Assure.NotNull(material); Assure.False(material.IsDisposed, "Given material was disposed!"); return(GeometryCache.GetCacheByID(modelHandle.GeoCacheID).AllocInstance(modelIndex, OwningLayer.Index, material.Index, initialTransform)); }
public unsafe void TestProperties() { // Define variables and constants const int FAKE_CACHE_ID = 1351617; IVertexBuffer[] buffers = new IVertexBuffer[2]; buffers[0] = BufferFactory.NewVertexBuffer <Vector3>() .WithInitialData(new[] { Vector3.ONE * 0f, Vector3.ONE * 1f, Vector3.ONE * 2f, Vector3.ONE * 3f, Vector3.ONE * 4f, Vector3.ONE * 5f }) .WithUsage(ResourceUsage.Immutable) .Create(); buffers[1] = BufferFactory.NewVertexBuffer <Vector2>() .WithInitialData(new[] { Vector2.ONE * 0f, Vector2.ONE * 1f, Vector2.ONE * 2f, Vector2.ONE * 3f, Vector2.ONE * 4f, Vector2.ONE * 5f }) .WithUsage(ResourceUsage.Immutable) .Create(); string[] semantics = { "POSITION", "TEXCOORD" }; ResourceFormat[] formats = { ResourceFormat.R32G32B32Float, ResourceFormat.R32G32Float }; IndexBuffer indices = BufferFactory.NewIndexBuffer() .WithInitialData(new uint[] { 0, 1, 2, 1, 2, 0, 2, 1, 0, 3, 4, 5, 4, 5, 3, 5, 3, 4, 5, 3, 4 }) .WithUsage(ResourceUsage.Immutable); AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3); *(((uint *)componentStartPointsAlloc.AlignedPointer) + 0) = 0U; *(((uint *)componentStartPointsAlloc.AlignedPointer) + 1) = 3U; *(((uint *)componentStartPointsAlloc.AlignedPointer) + 2) = 6U; AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3); *(((uint *)indexStartPointsAlloc.AlignedPointer) + 0) = 0U; *(((uint *)indexStartPointsAlloc.AlignedPointer) + 1) = 9U; *(((uint *)indexStartPointsAlloc.AlignedPointer) + 2) = 21U; Dictionary <string, ModelHandle> modelNameMap = new Dictionary <string, ModelHandle>() { { FAKE_CACHE_ID + "A", new ModelHandle(FAKE_CACHE_ID, 0U) }, { FAKE_CACHE_ID + "B", new ModelHandle(FAKE_CACHE_ID, 1U) } }; const uint NUM_MODELS = 2; // Set up context GeometryCache cache = new GeometryCache( buffers, semantics, formats, indices, componentStartPointsAlloc, indexStartPointsAlloc, NUM_MODELS, typeof(FakeVertex), FAKE_CACHE_ID, modelNameMap ); // Execute // Assert outcome Assert.AreEqual(buffers[0], cache.VertexBuffers[0]); Assert.AreEqual(buffers[1], cache.VertexBuffers[1]); Assert.AreEqual(semantics[0], cache.VertexSemantics[0]); Assert.AreEqual(semantics[1], cache.VertexSemantics[1]); Assert.AreEqual(formats[0], cache.VertexFormats[0]); Assert.AreEqual(formats[1], cache.VertexFormats[1]); Assert.AreEqual(indices, cache.IndexBuffer); cache.Dispose(); }
public void SetVSForCache(GeometryCache cache, VertexShader vs) { Assure.NotNull(cache); using (RenderingModule.RenderStateBarrier.AcquirePermit(withLock: InstanceMutationLock)) { if (vs == null) { deferredGeometryVertexShaders.Remove(cache); } else { deferredGeometryVertexShaders[cache] = vs; } } }
private Font(string name, uint lineHeightPixels, int kerningPixels, GeometryCache characterGeometry, ITexture2D[] characterPages, ShaderResourceView[] characterPageViews, Dictionary <char, FontCharacter> characters, ConstantBufferBinding textFsColorCbb, uint maxCharHeight) { Name = name; LineHeightPixels = lineHeightPixels; KerningPixels = kerningPixels; this.characterPages = characterPages; this.characters = characters; TextFSColorCBB = textFsColorCbb; MaxCharHeight = maxCharHeight; CharacterGeometry = characterGeometry; this.characterPageViews = characterPageViews; }
public void ShouldRejectDuplicateModelNames() { GeometryCacheBuilder <DefaultVertex> gcbA = new GeometryCacheBuilder <DefaultVertex>(); gcbA.AddModel("SRDMN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbA.AddModel("SRDMN_B", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcA = gcbA.Build(); GeometryCacheBuilder <DefaultVertex> gcbB = new GeometryCacheBuilder <DefaultVertex>(); gcbB.AddModel("SRDMN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbB.AddModel("SRDMN_2", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbB.AddModel("SRDMN_3", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcB = gcbB.Build(); GeometryCacheBuilder <DefaultVertex> gcbC = new GeometryCacheBuilder <DefaultVertex>(); gcbC.AddModel("SRDMN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); try { gcbC.Build(); Assert.Fail(); } catch (InvalidOperationException) { } gcbC = new GeometryCacheBuilder <DefaultVertex>(); gcbC.AddModel("SRDMN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); try { gcbC.Build(); Assert.Fail(); } catch (InvalidOperationException) { } gcbC = new GeometryCacheBuilder <DefaultVertex>(); gcbC.AddModel("SRDMN_X", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbC.AddModel("SRDMN_Y", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbC.AddModel("SRDMN_Z", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); gcbC.AddModel("SRDMN_Z", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); try { gcbC.Build(); Assert.Fail(); } catch (InvalidOperationException) { } gcA.Dispose(); gcB.Dispose(); }
internal unsafe GeometryInputLayout( InputLayoutHandle inputLayoutHandle, KeyValuePair <VertexInputBinding, IVertexBuffer>[] boundComponentBuffers, VertexShader associatedShader, GeometryCache associatedCache ) : base(inputLayoutHandle, ResourceUsage.Immutable, APPROX_INPUT_ELEMENT_DESC_SIZE_BYTES * boundComponentBuffers.Length) { BoundComponentBuffers = boundComponentBuffers; AssociatedShader = associatedShader; AssociatedCache = associatedCache; ResourcePackage = new ShaderResourcePackage(); foreach (KeyValuePair <VertexInputBinding, IVertexBuffer> pair in boundComponentBuffers) { ResourcePackage.SetValue(pair.Key, pair.Value); } }
public void TestSetInputLayout() { GeometryCacheBuilder <DefaultVertex> gcb = new GeometryCacheBuilder <DefaultVertex>(); gcb.AddModel("TSIL_a", new DefaultVertex[] { new DefaultVertex(Vector3.ONE) }, new uint[] { 0U }); GeometryCache cache = gcb.Build(); ConstantBuffer <Matrix> vpMat = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); VertexShader shader = new VertexShader( @"Tests\SimpleVS.cso", new VertexInputBinding(0U, "INSTANCE_TRANSFORM"), new ConstantBufferBinding(0U, "CameraTransform", vpMat), new VertexInputBinding(1U, "POSITION") ); GeometryInputLayout gil = cache.GetInputLayout(shader); RenderCommand testCommand = RenderCommand.SetInputLayout(gil); Assert.AreEqual(RenderCommandInstruction.SetInputLayout, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)gil.ResourceHandle, testCommand.Arg1); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetInputLayout(null); Assert.Fail(); } catch (AssuranceFailedException) { } #endif shader.Dispose(); vpMat.Dispose(); cache.Dispose(); gil.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetInputLayout(gil); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public void TestGettingModelsByName() { GeometryCacheBuilder <DefaultVertex> gcbA = new GeometryCacheBuilder <DefaultVertex>(); ModelHandle modelA = gcbA.AddModel("TGMBN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); ModelHandle modelB = gcbA.AddModel("TGMBN_B", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcA = gcbA.Build(); GeometryCacheBuilder <DefaultVertex> gcbB = new GeometryCacheBuilder <DefaultVertex>(); ModelHandle model1 = gcbB.AddModel("TGMBN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); ModelHandle model2 = gcbB.AddModel("TGMBN_2", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); ModelHandle model3 = gcbB.AddModel("TGMBN_3", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U }); GeometryCache gcB = gcbB.Build(); Assert.AreEqual(modelA, gcA.GetModelByName("TGMBN_A")); Assert.AreEqual(model3, gcB.GetModelByName("TGMBN_3")); Assert.AreEqual(model1, GeometryCache.GloballyGetModelByName("TGMBN_1")); Assert.AreEqual(model2, GeometryCache.GloballyGetModelByName("TGMBN_2")); Assert.AreEqual(modelB, GeometryCache.GloballyGetModelByName("TGMBN_B")); try { gcA.GetModelByName("TGMBN_1"); Assert.Fail(); } catch (KeyNotFoundException) { } try { gcB.GetModelByName("TGMBN_B"); Assert.Fail(); } catch (KeyNotFoundException) { } try { GeometryCache.GloballyGetModelByName("TGMBN_C"); Assert.Fail(); } catch (KeyNotFoundException) { } }
protected internal override void Execute(ParallelizationProvider pp) { DepthStencilViewHandle _; if (!output.TargetWindow.GetWindowRTVAndDSV(out windowRTVH, out _)) { return; } List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { // Set view/proj matrix Matrix vpMat = (*((Matrix *)Input.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(Input))).Transpose; byte * vpMapPtr = (byte *)&vpMat; VertexShader.ViewProjMatBinding.SetValue(vpMapPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread pp.InvokeOnAll(setUpCacheForLocalThreadAct, true); // also emits a membar // Iterate all model instances (ordered by material) pp.Execute((int)currentInstanceData.Length, (int)(currentInstanceData.Length / (pp.NumThreads << 3)) + 1, renderCacheIterateMatAct); // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); pp.InvokeOnAll(setInstanceBufferAndFlushCommandsAct, false); } // Present FlushRenderCommands(); if (presentAfterPass) { PresentBackBuffer(Output.TargetWindow); } }
/// <summary> /// Builds the <see cref="GeometryCache"/> with all the models that have previously been added with <see cref="AddModel"/>. /// This method may only be called once per GeometryCacheBuilder. /// </summary> /// <returns>A new <see cref="GeometryCache"/> containing 'baked' resource data for all the loaded models and an /// "instance pool", allowing model instances to be created and loaded in to the <see cref="Scene"/>.</returns> public unsafe GeometryCache Build() { lock (instanceMutationLock) { if (isBuilt) { throw new InvalidOperationException("Cache has already been built!"); } FieldInfo[] vertexComponents = typeof(TVertex).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (vertexComponents.Length > VertexShader.MAX_VS_INPUT_BINDINGS) { throw new InvalidOperationException("Vertex type '" + typeof(TVertex).Name + "' has too many components. Maximum " + "permissible is " + VertexShader.MAX_VS_INPUT_BINDINGS + ", but the vertex type has " + vertexComponents.Length + " fields."); } else if (vertexComponents.Length == 0) { throw new InvalidOperationException("Vertex type '" + typeof(TVertex).Name + "' has no components. Please choose a type with " + "at least one field."); } if (vertexCounts.Count == 0) { throw new InvalidOperationException("Can not build empty geometry cache: Please add at least one model first!"); } if (modelNames.AnyDuplicates()) { throw new InvalidOperationException("No two models should have the same name."); } if (GeometryCache.CheckForModelNameClashes(modelNames)) { throw new InvalidOperationException("One or more model names added to this builder have already been used in other active geometry caches."); } IVertexBuffer[] vertexComponentBuffers = new IVertexBuffer[vertexComponents.Length]; string[] vertexComponentSemantics = new string[vertexComponents.Length]; ResourceFormat[] vertexComponentFormats = new ResourceFormat[vertexComponents.Length]; for (int i = 0; i < vertexComponents.Length; ++i) { FieldInfo component = vertexComponents[i]; if (!component.FieldType.IsBlittable()) { throw new InvalidOperationException("Invalid vertex component type: '" + component.FieldType.Name + "'."); } if (!component.HasCustomAttribute <VertexComponentAttribute>()) { throw new InvalidOperationException("Every field on given vertex type (" + typeof(TVertex).Name + ") must be annoted with " + "a " + typeof(VertexComponentAttribute).Name + "!"); } typeof(GeometryCacheBuilder <TVertex>) .GetMethod("FillComponentBuffer", BindingFlags.NonPublic | BindingFlags.Instance) // TODO replace with nameof() operator when C#6 is released .MakeGenericMethod(component.FieldType) .Invoke(this, new object[] { component, i, vertexComponentBuffers, vertexComponentSemantics, vertexComponentFormats }); } IndexBuffer indexBuffer = BufferFactory.NewIndexBuffer().WithInitialData(indices.ToArray()).WithUsage(ResourceUsage.Immutable); Assure.Equal(vertexCounts.Count, indexCounts.Count); AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray( START_POINT_ARRAY_ALIGNMENT, (uint)vertexCounts.Count + 1U // Extra one so we can set the last value to one-past-the-end (performance improvement later on) ); AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray( START_POINT_ARRAY_ALIGNMENT, (uint)vertexCounts.Count + 1U // Extra one so we can set the last value to one-past-the-end (performance improvement later on) ); uint *componentStartPtr = (uint *)componentStartPointsAlloc.AlignedPointer; uint *indexStartPtr = (uint *)indexStartPointsAlloc.AlignedPointer; uint vbCounter = 0U; uint ibCounter = 0U; for (int i = 0; i < vertexCounts.Count; ++i) { componentStartPtr[i] = vbCounter; indexStartPtr[i] = ibCounter; vbCounter += vertexCounts[i]; ibCounter += indexCounts[i]; } // Set the last two elements of each start-point array to one-past-the-last, so we don't have to test // for being the 'last' count later on componentStartPtr[vertexCounts.Count] = (uint)vertices.Count; indexStartPtr[vertexCounts.Count] = (uint)indices.Count; Dictionary <string, ModelHandle> modelNameToHandleMap = new Dictionary <string, ModelHandle>(); for (uint i = 0U; i < modelNames.Count; ++i) { modelNameToHandleMap.Add(modelNames[(int)i], new ModelHandle(cacheID, i)); } isBuilt = true; return(new GeometryCache( vertexComponentBuffers, vertexComponentSemantics, vertexComponentFormats, indexBuffer, componentStartPointsAlloc, indexStartPointsAlloc, (uint)vertexCounts.Count, typeof(TVertex), cacheID, modelNameToHandleMap, orderFirst )); } }
public unsafe void TestGetModelBufferValues() { // Define variables and constants const int FAKE_CACHE_ID = 1351616; IVertexBuffer[] buffers = new IVertexBuffer[2]; buffers[0] = BufferFactory.NewVertexBuffer <Vector3>() .WithInitialData(new[] { Vector3.ONE * 0f, Vector3.ONE * 1f, Vector3.ONE * 2f, Vector3.ONE * 3f, Vector3.ONE * 4f, Vector3.ONE * 5f }) .WithUsage(ResourceUsage.Immutable) .Create(); buffers[1] = BufferFactory.NewVertexBuffer <Vector2>() .WithInitialData(new[] { Vector2.ONE * 0f, Vector2.ONE * 1f, Vector2.ONE * 2f, Vector2.ONE * 3f, Vector2.ONE * 4f, Vector2.ONE * 5f }) .WithUsage(ResourceUsage.Immutable) .Create(); string[] semantics = { "POSITION", "TEXCOORD" }; ResourceFormat[] formats = { ResourceFormat.R32G32B32Float, ResourceFormat.R32G32Float }; IndexBuffer indices = BufferFactory.NewIndexBuffer() .WithInitialData(new uint[] { 0, 1, 2, 1, 2, 0, 2, 1, 0, 3, 4, 5, 4, 5, 3, 5, 3, 4, 5, 3, 4 }) .WithUsage(ResourceUsage.Immutable); AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3); *(((uint *)componentStartPointsAlloc.AlignedPointer) + 0) = 0U; *(((uint *)componentStartPointsAlloc.AlignedPointer) + 1) = 3U; *(((uint *)componentStartPointsAlloc.AlignedPointer) + 2) = 6U; AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3); *(((uint *)indexStartPointsAlloc.AlignedPointer) + 0) = 0U; *(((uint *)indexStartPointsAlloc.AlignedPointer) + 1) = 9U; *(((uint *)indexStartPointsAlloc.AlignedPointer) + 2) = 21U; Dictionary <string, ModelHandle> modelNameMap = new Dictionary <string, ModelHandle>() { { FAKE_CACHE_ID + "A", new ModelHandle(FAKE_CACHE_ID, 0U) }, { FAKE_CACHE_ID + "B", new ModelHandle(FAKE_CACHE_ID, 1U) } }; const uint NUM_MODELS = 2; uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount; // Set up context GeometryCache cache = new GeometryCache( buffers, semantics, formats, indices, componentStartPointsAlloc, indexStartPointsAlloc, NUM_MODELS, typeof(FakeVertex), FAKE_CACHE_ID, modelNameMap ); // Execute cache.GetModelBufferValues(0U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); // Assert outcome Assert.AreEqual(0U, outVBStartIndex); Assert.AreEqual(0U, outIBStartIndex); Assert.AreEqual(3U, outVBCount); Assert.AreEqual(9U, outIBCount); cache.GetModelBufferValues(1U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.AreEqual(3U, outVBStartIndex); Assert.AreEqual(9U, outIBStartIndex); Assert.AreEqual(3U, outVBCount); Assert.AreEqual(12U, outIBCount); #if !DEVELOPMENT && !RELEASE try { cache.GetModelBufferValues(2U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.Fail(); } catch (AssuranceFailedException) { } #endif cache.Dispose(); }
public unsafe void TestGetInputLayout() { // Define variables and constants const int FAKE_CACHE_ID = 1351618; IVertexBuffer[] buffers = new IVertexBuffer[2]; buffers[0] = BufferFactory.NewVertexBuffer <Vector3>() .WithInitialData(new[] { Vector3.ONE * 0f, Vector3.ONE * 1f, Vector3.ONE * 2f, Vector3.ONE * 3f, Vector3.ONE * 4f, Vector3.ONE * 5f }) .WithUsage(ResourceUsage.Immutable) .Create(); buffers[1] = BufferFactory.NewVertexBuffer <float>() .WithInitialData(new[] { 0f, 1f, 2f, 3f, 4f, 5f }) .WithUsage(ResourceUsage.Immutable) .Create(); string[] semantics = { "POSITION", "RANDOM_FLOATS" }; ResourceFormat[] formats = { ResourceFormat.R32G32B32Float, ResourceFormat.R32G32Float }; IndexBuffer indices = BufferFactory.NewIndexBuffer() .WithInitialData(new uint[] { 0, 1, 2, 1, 2, 0, 2, 1, 0, 3, 4, 5, 4, 5, 3, 5, 3, 4, 5, 3, 4 }) .WithUsage(ResourceUsage.Immutable); AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3); *(((uint *)componentStartPointsAlloc.AlignedPointer) + 0) = 0U; *(((uint *)componentStartPointsAlloc.AlignedPointer) + 1) = 3U; *(((uint *)componentStartPointsAlloc.AlignedPointer) + 2) = 6U; AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3); *(((uint *)indexStartPointsAlloc.AlignedPointer) + 0) = 0U; *(((uint *)indexStartPointsAlloc.AlignedPointer) + 1) = 9U; *(((uint *)indexStartPointsAlloc.AlignedPointer) + 2) = 21U; Dictionary <string, ModelHandle> modelNameMap = new Dictionary <string, ModelHandle>() { { FAKE_CACHE_ID + "A", new ModelHandle(FAKE_CACHE_ID, 0U) }, { FAKE_CACHE_ID + "B", new ModelHandle(FAKE_CACHE_ID, 1U) } }; const uint NUM_MODELS = 2; // Set up context GeometryCache cache = new GeometryCache( buffers, semantics, formats, indices, componentStartPointsAlloc, indexStartPointsAlloc, NUM_MODELS, typeof(Vector4), FAKE_CACHE_ID, modelNameMap ); ConstantBuffer <Matrix> instanceCBuffer = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); VertexShader vs1 = new VertexShader( @"Tests\SimpleVS.cso", new VertexInputBinding(0U, "INSTANCE_TRANSFORM"), new ConstantBufferBinding(0U, "CameraTransform", instanceCBuffer), new VertexInputBinding(1U, "POSITION") ); VertexShader vs2 = new VertexShader( @"Tests\SimpleVS.cso", new VertexInputBinding(0U, "INSTANCE_TRANSFORM"), new ConstantBufferBinding(0U, "CameraTransform", instanceCBuffer), new VertexInputBinding(1U, "RANDOM_FLOATS"), new VertexInputBinding(2U, "POSITION") ); VertexShader vs3 = new VertexShader( @"Tests\SimpleVS.cso", new VertexInputBinding(0U, "INSTANCE"), new ConstantBufferBinding(0U, "VPTransform", instanceCBuffer), new VertexInputBinding(1U, "TEXCOORD") ); // Execute GeometryInputLayout inputLayout1 = cache.GetInputLayout(vs1); GeometryInputLayout inputLayout2 = cache.GetInputLayout(vs2); try { cache.GetInputLayout(vs3); Assert.Fail(); } catch (InvalidOperationException) { } // Assert outcome Assert.AreEqual(cache, inputLayout1.AssociatedCache); Assert.AreEqual(cache, inputLayout2.AssociatedCache); Assert.AreEqual(vs1, inputLayout1.AssociatedShader); Assert.AreEqual(vs2, inputLayout2.AssociatedShader); KeyValuePair <VertexInputBinding, IVertexBuffer>[] boundCompBuffers = inputLayout1.BoundComponentBuffers; Assert.AreEqual(buffers[0], boundCompBuffers.First(kvp => kvp.Key == vs1.GetBindingByIdentifier("POSITION")).Value); Assert.IsFalse(boundCompBuffers.Any(kvp => kvp.Value == buffers[1])); boundCompBuffers = inputLayout2.BoundComponentBuffers; Assert.AreEqual(buffers[0], boundCompBuffers.First(kvp => kvp.Key == vs2.GetBindingByIdentifier("POSITION")).Value); Assert.AreEqual(buffers[1], boundCompBuffers.First(kvp => kvp.Key == vs2.GetBindingByIdentifier("RANDOM_FLOATS")).Value); Assert.AreEqual(inputLayout1, cache.GetInputLayout(vs1)); Assert.AreEqual(inputLayout2, cache.GetInputLayout(vs2)); cache.Dispose(); inputLayout2.Dispose(); inputLayout1.Dispose(); vs1.Dispose(); vs2.Dispose(); vs3.Dispose(); instanceCBuffer.Dispose(); indices.Dispose(); buffers[1].Dispose(); buffers[0].Dispose(); }
protected internal unsafe override void Execute(ParallelizationProvider pp) { // See if we need to resize the depth buffer Vector2 viewportDimensions = output.SizePixels; if (viewportDimensions.X < 1f || viewportDimensions.Y < 1f) { return; } uint viewportX = (uint)viewportDimensions.X; uint viewportY = (uint)viewportDimensions.Y; if (shadowBuffer == null || shadowBufferDSV == null || shadowBufferDSV.ResourceOrViewDisposed || shadowBufferSRV == null || shadowBufferSRV.ResourceOrViewDisposed || shadowBuffer.Width != viewportX || shadowBuffer.Height != viewportY) { if (shadowBufferDSV != null && !shadowBufferDSV.IsDisposed) { shadowBufferDSV.Dispose(); } if (shadowBuffer != null && !shadowBuffer.IsDisposed) { shadowBuffer.Dispose(); } shadowBuffer = shadowBufferBuilder.WithWidth(viewportX).WithHeight(viewportY); shadowBufferDSV = shadowBuffer.CreateDepthStencilView <TexelFormat.DepthStencil>(0U); shadowBufferSRV = shadowBuffer.CreateView <TexelFormat.R24UnormX8Typeless>(0U, 1U); } // Clear the depth buffer QueueRenderCommand(RenderCommand.ClearDepthStencil(shadowBufferDSV)); List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { // Set view/proj matrix Matrix vpMat = (*((Matrix *)lightCam.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(lightCam))).Transpose; byte * vpMapPtr = (byte *)&vpMat; shadowVS.ViewProjMatBinding.SetValue(vpMapPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread pp.InvokeOnAll(setUpCacheForLocalThreadAct, true); // membar here // Iterate all model instances (ordered by material) pp.Execute((int)currentInstanceData.Length, (int)(currentInstanceData.Length / (pp.NumThreads << 3)) + 1, renderCacheIterateMatAct); // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); pp.InvokeOnAll(setInstanceBufferAndFlushCommandsAct, false); } }
protected internal override void Execute(ParallelizationProvider pp) { for (int i = 0; i < NUM_GBUFFER_TEXTURES; ++i) { if (gBufferViews[i] != null) { QueueRenderCommand(RenderCommand.ClearRenderTarget(gBufferViews[i])); } } if (clearOutputBeforePass) { QueueRenderCommand(RenderCommand.ClearRenderTarget(output.TargetWindow)); QueueRenderCommand(RenderCommand.ClearDepthStencil(output.TargetWindow)); } Vector2 outputSizePixels = output.SizePixels; if (gBuffer[0] == null || gBuffer[0].Width != (uint)outputSizePixels.X || gBuffer[0].Height != (uint)outputSizePixels.Y) { for (int i = 0; i < NUM_GBUFFER_TEXTURES; ++i) { if (gBufferViews[i] != null) { gBufferViews[i].Dispose(); } if (gBuffer[i] != null) { gBuffer[i].Dispose(); } gBuffer[i] = gBufferBuilder.WithWidth((uint)outputSizePixels.X).WithHeight((uint)outputSizePixels.Y); gBufferViews[i] = gBuffer[i].CreateRenderTargetView(0U); } } if (primaryDSBuffer == null || primaryDSBuffer.Width != outputSizePixels.X || primaryDSBuffer.Height != outputSizePixels.Y) { if (primaryDSBuffer != null) { primaryDSBuffer.Dispose(); } if (primaryDSBufferDSV != null) { primaryDSBufferDSV.Dispose(); } if (primaryDSBufferSRV != null) { primaryDSBufferSRV.Dispose(); } primaryDSBuffer = dsBufferBuilder.WithWidth((uint)outputSizePixels.X).WithHeight((uint)outputSizePixels.Y); primaryDSBufferDSV = primaryDSBuffer.CreateDepthStencilView <TexelFormat.DepthStencil>(0U); primaryDSBufferSRV = primaryDSBuffer.CreateView <TexelFormat.R24UnormX8Typeless>(0U, 1U); } previousShadowBufferSRV = shadowPass.ShadowBufferSRV; // Clear main DSV QueueRenderCommand(RenderCommand.ClearDepthStencil(primaryDSBufferDSV)); List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { if (!deferredGeometryVertexShaders.ContainsKey(c)) { continue; } currentVS = deferredGeometryVertexShaders[c]; // Set view/proj matrices var vpMatrices = new GeomPassProjViewMatrices { MainCameraVPMat = (*((Matrix *)Input.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(Input))).Transpose, ShadowCameraVPMat = (*((Matrix *)shadowPass.LightCam.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(shadowPass.LightCam))).Transpose }; byte *vpMatPtr = (byte *)&vpMatrices; currentVS.ViewProjMatBinding.SetValue(vpMatPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread pp.InvokeOnAll(setUpCacheForLocalThreadAct, true); // membar here // Iterate all model instances (ordered by material) pp.Execute((int)currentInstanceData.Length, (int)(currentInstanceData.Length / (pp.NumThreads << 3)) + 1, renderCacheIterateMatAct); // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Unbind shadow buffer QueueShaderSwitch(geomFSWithShadowSupport); QueueShaderResourceUpdate(geomFSWithShadowSupport, geomFSShadowUnbindPackage); // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); pp.InvokeOnAll(setInstanceBufferAndFlushCommandsAct, false); } }
public unsafe void TestCreateAndDestroyInstance() { // Define variables and constants const int NUM_INSTANCES = 1000; var gcb = new GeometryCacheBuilder <TestVertex>(); gcb.AddModel("TCADI_a", new[] { new TestVertex(Vector3.ONE), new TestVertex(Vector3.LEFT), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U }); gcb.AddModel("TCADI_b", new[] { new TestVertex(Vector3.RIGHT), new TestVertex(Vector3.UP), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U }); gcb.AddModel("TCADI_c", new[] { new TestVertex(Vector3.ZERO), new TestVertex(Vector3.DOWN), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U }); GeometryCache testCache = gcb.Build(); SceneLayer testLayerA = Scene.CreateLayer("Test Layer A"); SceneLayer testLayerB = Scene.CreateLayer("Test Layer B"); ConstantBuffer <Vector4> fsColorBuffer = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite); FragmentShader fs = new FragmentShader(@"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "MaterialProperties", fsColorBuffer)); Material testMatA = new Material("Brick", fs); Material testMatB = new Material("Wood", fs); // Set up context // Execute ModelInstanceHandle[] instanceArr = new ModelInstanceHandle[NUM_INSTANCES]; for (int i = 0; i < NUM_INSTANCES; ++i) { Transform transform = new Transform( Vector3.ONE * i, Quaternion.FromAxialRotation(Vector3.UP, i), Vector3.ONE * -i ); if (i % 5 == 0) { instanceArr[i] = testLayerA.CreateModelInstance(new ModelHandle(testCache.ID, (uint)(i % 3)), (i % 2 == 0 ? testMatA : testMatB), transform); } else { instanceArr[i] = testLayerB.CreateModelInstance(new ModelHandle(testCache.ID, (uint)(i % 3)), (i % 2 == 0 ? testMatA : testMatB), transform); } } // Assert outcome RenderingModule.RenderStateBarrier.FreezeMutations(); // Cheeky, but we have to on debug mode (and it's re-entrant for now, so no problem) var instanceData = testCache.GetModelInstanceData(); for (int i = 0; i < NUM_INSTANCES; ++i) { Material instanceMaterial = Material.GetMaterialByIndex(instanceArr[i].MaterialIndex); ModelInstanceManager.MIDArray materialDataArray = instanceData.First(kvp => kvp.Key == instanceMaterial).Value; Assert.AreEqual((i % 2 == 0 ? testMatA : testMatB), instanceMaterial); Assert.AreEqual((i % 5 == 0 ? testLayerA : testLayerB), Scene.GetLayerByIndex(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].SceneLayerIndex)); Assert.IsTrue(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].InUse); Assert.AreEqual((uint)(i % 3), materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].ModelIndex); Assert.AreEqual( new Transform( Vector3.ONE * i, Quaternion.FromAxialRotation(Vector3.UP, i), Vector3.ONE * -i ), instanceArr[i].Transform ); Assert.AreEqual(instanceArr[i].Transform, materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].Transform); instanceArr[i].Dispose(); Assert.IsFalse(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].InUse); } RenderingModule.RenderStateBarrier.UnfreezeMutations(); testCache.Dispose(); testMatA.Dispose(); testMatB.Dispose(); testLayerA.Dispose(); testLayerB.Dispose(); fs.Dispose(); fsColorBuffer.Dispose(); }
public void ShouldCookParametersCorrectly() { // Define variables and constants GeometryCacheBuilder <TestVertex> testVertexCacheBuilder = new GeometryCacheBuilder <TestVertex>(); int cacheID = (int)typeof(GeometryCacheBuilder <TestVertex>).GetField("cacheID", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(testVertexCacheBuilder); TestVertex[] model1Verts = { new TestVertex(Vector3.ONE * 0f, Vector2.ONE * 0f), new TestVertex(Vector3.ONE * 1f, Vector2.ONE * 1f), new TestVertex(Vector3.ONE * 2f, Vector2.ONE * 2f), }; TestVertex[] model2Verts = { new TestVertex(Vector3.ONE * 3f, Vector2.ONE * 3f), new TestVertex(Vector3.ONE * 4f, Vector2.ONE * 4f), new TestVertex(Vector3.ONE * 5f, Vector2.ONE * 5f), }; uint[] model1Indices = { 0U, 1U, 2U, 1U, 2U, 0U, 2U, 0U, 1U }; uint[] model2Indices = { 3U, 4U, 5U, 4U, 5U, 3U, 5U, 3U, 4U, 3U, 5U, 4U }; uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount; // Set up context Assert.AreEqual(new ModelHandle(cacheID, 0U), testVertexCacheBuilder.AddModel("SCPC_a", model1Verts, model1Indices)); Assert.AreEqual(new ModelHandle(cacheID, 1U), testVertexCacheBuilder.AddModel("SCPC_b", model2Verts, model2Indices)); // Execute GeometryCache result = testVertexCacheBuilder.Build(); // Assert outcome Assert.AreEqual(cacheID, result.ID); Assert.AreEqual(result, GeometryCache.GetCacheByID(cacheID)); Assert.AreEqual((uint)(model1Indices.Length + model2Indices.Length), result.IndexBuffer.Length); Assert.AreEqual((uint)(model1Verts.Length + model2Verts.Length), result.VertexBuffers[0].Length); Assert.AreEqual(2, result.VertexBuffers.Count); Assert.AreEqual(ResourceFormat.R32G32B32Float, result.VertexFormats[0]); Assert.AreEqual(ResourceFormat.R32G32Float, result.VertexFormats[1]); Assert.AreEqual(2U, result.NumModels); Assert.AreEqual(6U, result.NumVertices); Assert.AreEqual(typeof(VertexBuffer <Vector3>), result.VertexBuffers[0].GetType()); Assert.AreEqual(typeof(VertexBuffer <Vector2>), result.VertexBuffers[1].GetType()); Assert.AreEqual("POSITION", result.VertexSemantics[0]); Assert.AreEqual("TEXCOORD", result.VertexSemantics[1]); result.GetModelBufferValues(0U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.AreEqual(0U, outVBStartIndex); Assert.AreEqual(0U, outIBStartIndex); Assert.AreEqual(3U, outVBCount); Assert.AreEqual(9U, outIBCount); result.GetModelBufferValues(1U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.AreEqual(3U, outVBStartIndex); Assert.AreEqual(9U, outIBStartIndex); Assert.AreEqual(3U, outVBCount); Assert.AreEqual(12U, outIBCount); #if !DEVELOPMENT && !RELEASE try { result.GetModelBufferValues(2U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); Assert.Fail(); } catch (AssuranceFailedException) { } #endif result.Dispose(); }
protected internal override void Execute(ParallelizationProvider pp) { // Set up buffers if (!output.TargetWindow.GetWindowRTVAndDSV(out windowRTVH, out windowDSVH)) { return; } Vector2 viewportSizePixels = output.TargetWindow.AddedViewports.First().SizePixels; if (viewportSizePixels.X <= 0f || viewportSizePixels.Y <= 0f) { return; } SetUpBuffers(viewportSizePixels); // Clear pre-glow buffer QueueRenderCommand(RenderCommand.ClearRenderTarget(preGlowTargetBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(glowSrcBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(glowDstBufferRTV)); List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { // Set view/proj matrix Matrix vpMat = (*((Matrix *)Input.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(Input))).Transpose; byte * vpMapPtr = (byte *)&vpMat; VertexShader.ViewProjMatBinding.SetValue(vpMapPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread SetUpCacheForLocalThread(); // Iterate all model instances (ordered by material && ZIndex) //if (instanceDataSortSpace.Length < currentInstanceData.Length) instanceDataSortSpace = new KeyValuePair<Material, ModelInstanceManager.MIDArray>[currentInstanceData.Length * 2]; //for (int i = 0; i < currentInstanceData.Length; i += 2) { // var a = currentInstanceData[i]; // if (currentInstanceData.Length == i + 1) { // if (currentInstanceData.Length >= 3) { // if (a.Key.ZIndex < instanceDataSortSpace[i - 2].Key.ZIndex) { // instanceDataSortSpace[i] = instanceDataSortSpace[i - 1]; // instanceDataSortSpace[i - 1] = instanceDataSortSpace[i - 2]; // instanceDataSortSpace[i - 2] = a; // } // else if (a.Key.ZIndex < instanceDataSortSpace[i - 1].Key.ZIndex) { // instanceDataSortSpace[i] = instanceDataSortSpace[i - 1]; // instanceDataSortSpace[i - 1] = a; // } // else instanceDataSortSpace[i] = a; // } // else instanceDataSortSpace[i] = a; // } // else { // var b = currentInstanceData[i + 1]; // if (a.Key.ZIndex <= b.Key.ZIndex) { // instanceDataSortSpace[i] = a; // instanceDataSortSpace[i + 1] = b; // } // else { // instanceDataSortSpace[i] = b; // instanceDataSortSpace[i + 1] = a; // } // } //} Array.Sort(currentInstanceData.ContainingArray, 0, (int)currentInstanceData.Length, zIndexComparer); foreach (KeyValuePair <Material, ModelInstanceManager.MIDArray> material in currentInstanceData) { for (int i = 0; i < currentInstanceData.Length; ++i) { if (currentInstanceData[i].Value == material.Value && currentInstanceData[i].Key == material.Key) { RenderCache_IterateMaterial(i); break; } } } // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); } ///* ============================================= // * PREPARE FOR GLOW // * ============================================= */ //// Clear glow buffers //QueueRenderCommand(RenderCommand.ClearRenderTarget(glowSrcBufferRTV)); //// Set blend state //QueueRenderCommand(RenderCommand.SetBlendState(glowBlendState)); //// Set topology //QueueRenderCommand(RenderCommand.SetPrimitiveTopology(RenderCommand.DEFAULT_PRIMITIVE_TOPOLOGY)); //// Set input layout //QueueRenderCommand(RenderCommand.SetInputLayout(glowPlaneInputLayout)); //// Enqueue VS commands //QueueShaderSwitch(glowVS); //QueueShaderResourceUpdate(glowVS); ///* ============================================= // * DOWNSCALE TO GLOW SRC BUFFER // * ============================================= */ //// Set up output merger //QueueRenderCommand(RenderCommand.SetRenderTargets(glowDSBufferDSV, glowSrcBufferRTV)); //// Switch to copy shader //QueueShaderSwitch(scaleDownShader); //QueueShaderResourceUpdate(scaleDownShader, scaleDownShaderResPkg); //// Draw fullscreen triangles //QueueRenderCommand(RenderCommand.Draw(0, 3U)); //QueueRenderCommand(RenderCommand.Draw(3, 3U)); //// Unbind resources //QueueShaderResourceUpdate(scaleDownShader, scaleDownShaderResUnbindPkg); ///* ============================================= // * RENDER GLOW // * ============================================= */ //// Set up output merger //QueueRenderCommand(RenderCommand.SetRenderTargets(glowDSBufferDSV, glowDstBufferRTV)); //// Switch to glow shader //QueueShaderSwitch(glowShader); //QueueShaderResourceUpdate(glowShader, glowShaderVResPkg); //// Set blend state //QueueRenderCommand(RenderCommand.SetBlendState(dstMergeBlend)); //// Draw fullscreen triangles //QueueRenderCommand(RenderCommand.Draw(0, 3U)); //QueueRenderCommand(RenderCommand.Draw(3, 3U)); //// Unbind resources //QueueShaderResourceUpdate(glowShader, glowShaderVResUnbindPkg); ///* ============================================= // * UPSCALE TO BACK BUFFER // * ============================================= */ //// Set up output merger //QueueRenderCommand(RenderCommand.SetRenderTargets(output.TargetWindow)); //// Switch to copy shader //QueueShaderSwitch(scaleUpShader); //QueueShaderResourceUpdate(scaleUpShader, scaleUpShaderResPkg); //// Draw fullscreen triangles //QueueRenderCommand(RenderCommand.Draw(0, 3U)); //QueueRenderCommand(RenderCommand.Draw(3, 3U)); //// Unbind resources //QueueShaderResourceUpdate(scaleUpShader, scaleUpShaderResUnbindPkg); // Present FlushRenderCommands(); if (presentAfterPass) { PresentBackBuffer(Output.TargetWindow); } }