/// <summary> /// Function to return the dispatch call. /// </summary> /// <param name="allocator">The allocator used to create an instance of the object</param> /// <returns>The dispatch call created or updated by this builder.</returns> /// <exception cref="GorgonException">Thrown if a <see cref="GorgonComputeShader"/> is not assigned to the <see cref="GorgonComputeShader"/> property with the <see cref="ComputeShader"/> command.</exception> /// <remarks> /// <para> /// Using an <paramref name="allocator"/> can provide different strategies when building dispatch calls. If omitted, the dispatch call will be created using the standard <see langword="new"/> keyword. /// </para> /// <para> /// A custom allocator can be beneficial because it allows us to use a pool for allocating the objects, and thus allows for recycling of objects. This keeps the garbage collector happy by keeping objects /// around for as long as we need them, instead of creating objects that can potentially end up in the large object heap or in Gen 2. /// </para> /// <para> /// A dispatch call requires that at least a vertex shader be bound. If none is present, then the method will throw an exception. /// </para> /// </remarks> public GorgonDispatchCall Build(GorgonRingPool <GorgonDispatchCall> allocator) { var final = new GorgonDispatchCall(); final.Setup(); // Copy over the available constants. StateCopy.CopyConstantBuffers(final.D3DState.CsConstantBuffers, _worker.D3DState.CsConstantBuffers, 0); // Copy over samplers. StateCopy.CopySamplers(final.D3DState.CsSamplers, _worker.D3DState.CsSamplers, 0); // Copy over shader resource views. (int _, int _) = _worker.D3DState.CsSrvs.GetDirtyItems(); StateCopy.CopySrvs(final.D3DState.CsSrvs, _worker.D3DState.CsSrvs); // Copy over unordered access views. StateCopy.CopyReadWriteViews(final.D3DState.CsReadWriteViews, _worker.D3DState.CsReadWriteViews, 0); if (_worker.D3DState.ComputeShader == null) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_ERR_NO_COMPUTE_SHADER); } final.D3DState.ComputeShader = _worker.D3DState.ComputeShader; return(final); }
/// <summary> /// Function to assign the list of shader resource views to the draw call. /// </summary> /// <param name="shaderType">The shader stage to use.</param> /// <param name="resourceViews">The shader resource views to copy.</param> /// <param name="startSlot">[Optional] The starting slot to use when copying the list.</param> /// <returns>The fluent builder interface .</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="startSlot"/> is less than 0, or greater than/equal to <see cref="GorgonShaderResourceViews.MaximumShaderResourceViewCount"/>.</exception> /// <exception cref="NotSupportedException">Thrown if the <paramref name="shaderType"/> is not valid.</exception> /// <remarks> /// <para> /// <see cref="ShaderType.Compute"/> shaders are not supported in this method will throw an exception. /// </para> /// </remarks> public TB ShaderResources(ShaderType shaderType, IReadOnlyList <GorgonShaderResourceView> resourceViews, int startSlot = 0) { if ((startSlot < 0) || (startSlot >= GorgonShaderResourceViews.MaximumShaderResourceViewCount)) { throw new ArgumentOutOfRangeException(nameof(startSlot), string.Format(Resources.GORGFX_ERR_SRV_SLOT_INVALID, GorgonShaderResourceViews.MaximumShaderResourceViewCount)); } switch (shaderType) { case ShaderType.Pixel: StateCopy.CopySrvs(DrawCall.D3DState.PsSrvs, resourceViews, startSlot); break; case ShaderType.Vertex: StateCopy.CopySrvs(DrawCall.D3DState.VsSrvs, resourceViews, startSlot); break; case ShaderType.Geometry: StateCopy.CopySrvs(DrawCall.D3DState.GsSrvs, resourceViews, startSlot); break; case ShaderType.Domain: StateCopy.CopySrvs(DrawCall.D3DState.DsSrvs, resourceViews, startSlot); break; case ShaderType.Hull: StateCopy.CopySrvs(DrawCall.D3DState.HsSrvs, resourceViews, startSlot); break; default: throw new NotSupportedException(string.Format(Resources.GORGFX_ERR_SHADER_UNKNOWN_TYPE, shaderType)); } return((TB)this); }
/// <summary> /// Function to assign the list of shader resource views to the dispatch call. /// </summary> /// <param name="resourceViews">The shader resource views to copy.</param> /// <param name="startSlot">[Optional] The starting slot to use when copying the list.</param> /// <returns>The fluent builder interface .</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="startSlot"/> is less than 0, or greater than/equal to <see cref="GorgonShaderResourceViews.MaximumShaderResourceViewCount"/>.</exception> public GorgonDispatchCallBuilder ShaderResources(IReadOnlyList <GorgonShaderResourceView> resourceViews, int startSlot = 0) { if ((startSlot < 0) || (startSlot >= GorgonShaderResourceViews.MaximumShaderResourceViewCount)) { throw new ArgumentOutOfRangeException(nameof(startSlot), string.Format(Resources.GORGFX_ERR_SRV_SLOT_INVALID, GorgonShaderResourceViews.MaximumShaderResourceViewCount)); } StateCopy.CopySrvs(_worker.D3DState.CsSrvs, resourceViews, startSlot); return(this); }
/// <summary> /// Function to reset the builder to the specified draw call state. /// </summary> /// <param name="drawCall">[Optional] The specified draw call state to copy.</param> /// <returns>The fluent builder interface.</returns> public TB ResetTo(TDc drawCall = null) { if (drawCall == null) { return(Clear()); } VertexBuffers(drawCall.InputLayout, drawCall.VertexBufferBindings); StreamOutBuffers(drawCall.StreamOutBufferBindings); // Copy over the available constants. ConstantBuffers(ShaderType.Pixel, drawCall.D3DState.PsConstantBuffers); ConstantBuffers(ShaderType.Vertex, drawCall.D3DState.VsConstantBuffers); ConstantBuffers(ShaderType.Geometry, drawCall.D3DState.GsConstantBuffers); ConstantBuffers(ShaderType.Domain, drawCall.D3DState.DsConstantBuffers); ConstantBuffers(ShaderType.Hull, drawCall.D3DState.HsConstantBuffers); SamplerStates(ShaderType.Pixel, drawCall.D3DState.PsSamplers); SamplerStates(ShaderType.Vertex, drawCall.D3DState.VsSamplers); SamplerStates(ShaderType.Geometry, drawCall.D3DState.GsSamplers); SamplerStates(ShaderType.Domain, drawCall.D3DState.DsSamplers); SamplerStates(ShaderType.Hull, drawCall.D3DState.HsSamplers); StateCopy.CopySrvs(DrawCall.D3DState.PsSrvs, drawCall.D3DState.PsSrvs); StateCopy.CopySrvs(DrawCall.D3DState.VsSrvs, drawCall.D3DState.VsSrvs); StateCopy.CopySrvs(DrawCall.D3DState.GsSrvs, drawCall.D3DState.GsSrvs); StateCopy.CopySrvs(DrawCall.D3DState.DsSrvs, drawCall.D3DState.DsSrvs); StateCopy.CopySrvs(DrawCall.D3DState.HsSrvs, drawCall.D3DState.HsSrvs); ReadWriteViews(drawCall.D3DState.ReadWriteViews); DrawCall.D3DState.PipelineState = new GorgonPipelineState(drawCall.PipelineState); // We need to copy the D3D states as well as they won't be updated unless we rebuild the pipeline state. DrawCall.D3DState.PipelineState.D3DBlendState = drawCall.D3DState.PipelineState.D3DBlendState; DrawCall.D3DState.PipelineState.D3DRasterState = drawCall.D3DState.PipelineState.D3DRasterState; DrawCall.D3DState.PipelineState.D3DDepthStencilState = drawCall.D3DState.PipelineState.D3DDepthStencilState; return(OnResetTo(drawCall)); }
/// <summary> /// Function to return the draw call. /// </summary> /// <param name="allocator">The allocator used to create an instance of the object</param> /// <returns>The draw call created or updated by this builder.</returns> /// <exception cref="GorgonException">Thrown if a <see cref="GorgonVertexShader"/> is not assigned to the <see cref="GorgonPipelineState.VertexShader"/> property with the <see cref="PipelineState(GorgonPipelineStateBuilder)"/> command.</exception> /// <remarks> /// <para> /// Using an <paramref name="allocator"/> can provide different strategies when building draw calls. If omitted, the draw call will be created using the standard <see langword="new"/> keyword. /// </para> /// <para> /// A custom allocator can be beneficial because it allows us to use a pool for allocating the objects, and thus allows for recycling of objects. This keeps the garbage collector happy by keeping objects /// around for as long as we need them, instead of creating objects that can potentially end up in the large object heap or in Gen 2. /// </para> /// <para> /// A draw call requires that at least a vertex shader be bound. If none is present, then the method will throw an exception. /// </para> /// </remarks> public TDc Build(GorgonDrawCallPoolAllocator <TDc> allocator) { TDc final = OnCreate(allocator); if ((allocator == null) || (final.VertexShader.ConstantBuffers == null) || (final.PixelShader.Samplers == null) || (final.PixelShader.ShaderResources == null)) { final.SetupConstantBuffers(); final.SetupSamplers(); final.SetupViews(); } if (final.D3DState.VertexBuffers == null) { final.D3DState.VertexBuffers = new GorgonVertexBufferBindings(); } if (final.D3DState.StreamOutBindings == null) { final.D3DState.StreamOutBindings = new GorgonStreamOutBindings(); } StateCopy.CopyVertexBuffers(final.D3DState.VertexBuffers, DrawCall.VertexBufferBindings, DrawCall.InputLayout); StateCopy.CopyStreamOutBuffers(final.D3DState.StreamOutBindings, DrawCall.StreamOutBufferBindings); // Copy over the shader resources. if (DrawCall.D3DState.PipelineState?.PixelShader != null) { StateCopy.CopyConstantBuffers(final.D3DState.PsConstantBuffers, DrawCall.D3DState.PsConstantBuffers, 0); StateCopy.CopySamplers(final.D3DState.PsSamplers, DrawCall.D3DState.PsSamplers, 0); StateCopy.CopySrvs(final.D3DState.PsSrvs, DrawCall.D3DState.PsSrvs); } else { final.D3DState.PsConstantBuffers.Clear(); final.D3DState.PsSamplers.Clear(); final.D3DState.PsSrvs.Clear(); } if (DrawCall.D3DState.PipelineState?.VertexShader != null) { StateCopy.CopyConstantBuffers(final.D3DState.VsConstantBuffers, DrawCall.D3DState.VsConstantBuffers, 0); StateCopy.CopySamplers(final.D3DState.VsSamplers, DrawCall.D3DState.VsSamplers, 0); StateCopy.CopySrvs(final.D3DState.VsSrvs, DrawCall.D3DState.VsSrvs); } else { final.D3DState.VsConstantBuffers.Clear(); final.D3DState.VsSamplers.Clear(); final.D3DState.VsSrvs.Clear(); } if (DrawCall.D3DState.PipelineState?.GeometryShader != null) { StateCopy.CopyConstantBuffers(final.D3DState.GsConstantBuffers, DrawCall.D3DState.GsConstantBuffers, 0); StateCopy.CopySamplers(final.D3DState.GsSamplers, DrawCall.D3DState.GsSamplers, 0); StateCopy.CopySrvs(final.D3DState.GsSrvs, DrawCall.D3DState.GsSrvs); } else { final.D3DState.GsConstantBuffers.Clear(); final.D3DState.GsSamplers.Clear(); final.D3DState.GsSrvs.Clear(); } if (DrawCall.D3DState.PipelineState?.DomainShader != null) { StateCopy.CopyConstantBuffers(final.D3DState.DsConstantBuffers, DrawCall.D3DState.DsConstantBuffers, 0); StateCopy.CopySamplers(final.D3DState.DsSamplers, DrawCall.D3DState.DsSamplers, 0); StateCopy.CopySrvs(final.D3DState.DsSrvs, DrawCall.D3DState.DsSrvs); } else { final.D3DState.DsConstantBuffers.Clear(); final.D3DState.DsSamplers.Clear(); final.D3DState.DsSrvs.Clear(); } if (DrawCall.D3DState.PipelineState?.HullShader != null) { StateCopy.CopyConstantBuffers(final.D3DState.HsConstantBuffers, DrawCall.D3DState.HsConstantBuffers, 0); StateCopy.CopySamplers(final.D3DState.HsSamplers, DrawCall.D3DState.HsSamplers, 0); StateCopy.CopySrvs(final.D3DState.HsSrvs, DrawCall.D3DState.HsSrvs); } else { final.D3DState.HsConstantBuffers.Clear(); final.D3DState.HsSamplers.Clear(); final.D3DState.HsSrvs.Clear(); } // Copy over unordered access views. StateCopy.CopyReadWriteViews(final.D3DState.ReadWriteViews, DrawCall.D3DState.ReadWriteViews, 0); final.D3DState.PipelineState = DrawCall.PipelineState; // Copy the cached states. final.PipelineState.D3DBlendState = DrawCall.PipelineState.D3DBlendState; final.PipelineState.D3DDepthStencilState = DrawCall.PipelineState.D3DDepthStencilState; final.PipelineState.D3DRasterState = DrawCall.PipelineState.D3DRasterState; OnUpdate(final); if (final.PipelineState.VertexShader == null) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_ERR_NO_VERTEX_SHADER); } return(final); }