/// <summary> /// Serializes an array of static <see cref="StreamOutputElement"/>s. /// </summary> /// <param name="valueArray">An array of <see cref="StreamOutputElement"/>s to serialize</param> /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param> /// <remarks> /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value. /// </remarks> public void Serialize(ref StreamOutputElement[] valueArray, SerializeFlags serializeFlags = SerializeFlags.Normal) { int storeObjectRef; if (SerializeIsNull(ref valueArray, out storeObjectRef, serializeFlags)) return; if (Mode == SerializerMode.Write) { // Store ObjectRef if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef); WriteArrayLength(valueArray.Length); for (int i = 0; i < valueArray.Length; i++) Serialize(ref valueArray[i], serializeFlags); } else { var count = ReadArrayLength(); valueArray = new StreamOutputElement[count]; // Store ObjectRef if (storeObjectRef >= 0) StoreObjectRef(valueArray, storeObjectRef); for (int index = 0; index < count; index++) Serialize(ref valueArray[index], serializeFlags); } }
private void CreateShaders() { foreach (var shaderBytecode in effectBytecode.Stages) { var bytecodeRaw = shaderBytecode.Data; var reflection = effectBytecode.Reflection; // TODO CACHE Shaders with a bytecode hash switch (shaderBytecode.Stage) { case ShaderStage.Vertex: vertexShader = new VertexShader(GraphicsDevice.NativeDevice, bytecodeRaw); // Note: input signature can be reused when reseting device since it only stores non-GPU data, // so just keep it if it has already been created before. if (inputSignature == null) inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shaderBytecode.Id, bytecodeRaw)); break; case ShaderStage.Domain: domainShader = new DomainShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; case ShaderStage.Hull: hullShader = new HullShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; case ShaderStage.Geometry: if (reflection.ShaderStreamOutputDeclarations != null && reflection.ShaderStreamOutputDeclarations.Count > 0) { // Calculate the strides var soStrides = new List<int>(); foreach (var streamOutputElement in reflection.ShaderStreamOutputDeclarations) { for (int i = soStrides.Count; i < (streamOutputElement.Stream + 1); i++) { soStrides.Add(0); } soStrides[streamOutputElement.Stream] += streamOutputElement.ComponentCount * sizeof(float); } var soElements = new StreamOutputElement[0]; // TODO CREATE StreamOutputElement from bytecode.Reflection.ShaderStreamOutputDeclarations geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw, soElements, soStrides.ToArray(), reflection.StreamOutputRasterizedStream); } else { geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw); } break; case ShaderStage.Pixel: pixelShader = new PixelShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; case ShaderStage.Compute: computeShader = new ComputeShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; } } }
/// <summary> /// Initializes a new instance of the <see cref = "T:SharpDX.Direct3D11.GeometryShader" /> class. /// </summary> /// <param name = "device">The device used to create the shader.</param> /// <param name = "shaderBytecode">The compiled shader bytecode.</param> /// <param name = "elements">An array of <see cref = "T:SharpDX.Direct3D11.StreamOutputElement" /> instances describing the layout of the output buffers.</param> /// <param name = "bufferedStrides">An array of buffer strides; each stride is the size of an element for that buffer.</param> /// <param name = "rasterizedStream">The index number of the stream to be sent to the rasterizer stage. Set to NoRasterizedStream if no stream is to be rasterized.</param> /// <param name = "linkage">A dynamic class linkage interface.</param> public GeometryShader(Device device, byte[] shaderBytecode, StreamOutputElement[] elements, int[] bufferedStrides, int rasterizedStream, ClassLinkage linkage = null) : base(IntPtr.Zero) { unsafe { fixed (void* pBuffer = shaderBytecode) device.CreateGeometryShaderWithStreamOutput((IntPtr)pBuffer, shaderBytecode.Length, elements, elements.Length, bufferedStrides, bufferedStrides.Length, rasterizedStream, linkage, this); } }
/// <summary> /// Serializes a static <see cref="StreamOutputElement"/>. /// </summary> /// <param name="value">The <see cref="StreamOutputElement"/> to serialize</param> /// <param name="serializeFlags">Type of serialization, see <see cref="SerializeFlags"/>.</param> /// <remarks> /// Note that depending on the serialization <see cref="Mode"/>, this method reads or writes the value. /// </remarks> public void Serialize(ref StreamOutputElement value, SerializeFlags serializeFlags = SerializeFlags.Normal) { int storeObjectRef; if (SerializeIsNull(ref value, out storeObjectRef, serializeFlags)) return; if (Mode == SerializerMode.Read) value = new StreamOutputElement(); // Store ObjectRef if (storeObjectRef >= 0) StoreObjectRef(value, storeObjectRef); Serialize(ref value.Stream); Serialize(ref value.SemanticName); Serialize(ref value.SemanticIndex); Serialize(ref value.StartComponent); Serialize(ref value.ComponentCount); Serialize(ref value.OutputSlot); }
internal unsafe MyFoliageGeneratingPass() { var soElements = new StreamOutputElement[2]; soElements[0].Stream = 0; soElements[0].SemanticName = "TEXCOORD"; soElements[0].SemanticIndex = 0; soElements[0].ComponentCount = 3; soElements[0].OutputSlot = 0; soElements[1].Stream = 0; soElements[1].SemanticName = "TEXCOORD"; soElements[1].SemanticIndex = 1; soElements[1].ComponentCount = 1; soElements[1].OutputSlot = 0; var soStrides = new int[] { sizeof(Vector3) + sizeof(uint) }; if(m_geometryShader == GeometryShaderId.NULL) m_geometryShader = MyShaders.CreateGs("passes/foliage_streaming/geometry_stage.hlsl", null, new MyShaderStreamOutputInfo { Elements = soElements, Strides = soStrides, RasterizerStreams = GeometryShader.StreamOutputNoRasterizedStream }); SetImmediate(true); }
internal unsafe MyFoliageGeneratingPass() { var soElements = new StreamOutputElement[2]; soElements[0].Stream = 0; soElements[0].SemanticName = "TEXCOORD"; soElements[0].SemanticIndex = 0; soElements[0].ComponentCount = 3; soElements[0].OutputSlot = 0; soElements[1].Stream = 0; soElements[1].SemanticName = "TEXCOORD"; soElements[1].SemanticIndex = 1; soElements[1].ComponentCount = 1; soElements[1].OutputSlot = 0; var soStrides = new int[] { sizeof(Vector3) + sizeof(uint) }; if(m_geometryShader == GeometryShaderId.NULL) { string stageFile = Path.Combine(MyMaterialShaders.PassesFolder, MyMaterialShaders.FOLIAGE_STREAMING_PASS, "GeometryStage.hlsl"); m_geometryShader = MyShaders.CreateGs(stageFile, null, new MyShaderStreamOutputInfo { Elements = soElements, Strides = soStrides, RasterizerStreams = GeometryShader.StreamOutputNoRasterizedStream }); } SetImmediate(true); }
internal DeviceChild GetOrCompileShader(EffectShaderType shaderType, int index, int soRasterizedStream, StreamOutputElement[] soElements, out string profileError) { DeviceChild shader = null; profileError = null; lock (sync) { shader = compiledShadersGroup[(int)shaderType][index]; if (shader == null) { if (RegisteredShaders[index].Level > graphicsDevice.Features.Level) { profileError = string.Format("{0}", RegisteredShaders[index].Level); return null; } var bytecodeRaw = RegisteredShaders[index].Bytecode; switch (shaderType) { case EffectShaderType.Vertex: shader = new VertexShader(graphicsDevice, bytecodeRaw); break; case EffectShaderType.Domain: shader = new DomainShader(graphicsDevice, bytecodeRaw); break; case EffectShaderType.Hull: shader = new HullShader(graphicsDevice, bytecodeRaw); break; case EffectShaderType.Geometry: if (soElements != null) { // Calculate the strides var soStrides = new List<int>(); foreach (var streamOutputElement in soElements) { for (int i = soStrides.Count; i < (streamOutputElement.Stream+1); i++) { soStrides.Add(0); } soStrides[streamOutputElement.Stream] += streamOutputElement.ComponentCount * sizeof(float); } shader = new GeometryShader(graphicsDevice, bytecodeRaw, soElements, soStrides.ToArray(), soRasterizedStream); } else { shader = new GeometryShader(graphicsDevice, bytecodeRaw); } break; case EffectShaderType.Pixel: shader = new PixelShader(graphicsDevice, bytecodeRaw); break; case EffectShaderType.Compute: shader = new ComputeShader(graphicsDevice, bytecodeRaw); break; } compiledShadersGroup[(int)shaderType][index] = ToDispose(shader); } } return shader; }
static void Main() { if (!SharpDevice.IsDirectX11Supported()) { System.Windows.Forms.MessageBox.Show("DirectX11 Not Supported"); return; } //Init textured cube int[] indices = new int[] { 0,1,2,0,2,3, 4,6,5,4,7,6, 8,9,10,8,10,11, 12,14,13,12,15,14, 16,18,17,16,19,18, 20,21,22,20,22,23 }; TexturedVertex[] vertices = new[] { ////TOP new TexturedVertex(new Vector3(-5,5,5),new Vector2(1,1)), new TexturedVertex(new Vector3(5,5,5),new Vector2(0,1)), new TexturedVertex(new Vector3(5,5,-5),new Vector2(0,0)), new TexturedVertex(new Vector3(-5,5,-5),new Vector2(1,0)), //BOTTOM new TexturedVertex(new Vector3(-5,-5,5),new Vector2(1,1)), new TexturedVertex(new Vector3(5,-5,5),new Vector2(0,1)), new TexturedVertex(new Vector3(5,-5,-5),new Vector2(0,0)), new TexturedVertex(new Vector3(-5,-5,-5),new Vector2(1,0)), //LEFT new TexturedVertex(new Vector3(-5,-5,5),new Vector2(0,1)), new TexturedVertex(new Vector3(-5,5,5),new Vector2(0,0)), new TexturedVertex(new Vector3(-5,5,-5),new Vector2(1,0)), new TexturedVertex(new Vector3(-5,-5,-5),new Vector2(1,1)), //RIGHT new TexturedVertex(new Vector3(5,-5,5),new Vector2(1,1)), new TexturedVertex(new Vector3(5,5,5),new Vector2(1,0)), new TexturedVertex(new Vector3(5,5,-5),new Vector2(0,0)), new TexturedVertex(new Vector3(5,-5,-5),new Vector2(0,1)), //FRONT new TexturedVertex(new Vector3(-5,5,5),new Vector2(1,0)), new TexturedVertex(new Vector3(5,5,5),new Vector2(0,0)), new TexturedVertex(new Vector3(5,-5,5),new Vector2(0,1)), new TexturedVertex(new Vector3(-5,-5,5),new Vector2(1,1)), //BACK new TexturedVertex(new Vector3(-5,5,-5),new Vector2(0,0)), new TexturedVertex(new Vector3(5,5,-5),new Vector2(1,0)), new TexturedVertex(new Vector3(5,-5,-5),new Vector2(1,1)), new TexturedVertex(new Vector3(-5,-5,-5),new Vector2(0,1)) }; //render form RenderForm form = new RenderForm(); form.Text = "Tutorial 14: Output Stream"; SharpFPS fpsCounter = new SharpFPS(); using (SharpDevice device = new SharpDevice(form)) { //Init font SharpBatch font = new SharpBatch(device, "textfont.dds"); //Init Mesh SharpMesh mesh = SharpMesh.Create<TexturedVertex>(device, vertices, indices); //Init shader from file SharpShader shader = new SharpShader(device, "../../HLSL.txt", new SharpShaderDescription() { VertexShaderFunction = "VS", PixelShaderFunction = "PS" }, new InputElement[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0) }); //output stream element declaration StreamOutputElement[] soDeclaration = new StreamOutputElement[] { new StreamOutputElement(){SemanticName="POSITION",ComponentCount=3}, new StreamOutputElement(){SemanticName="TEXCOORD",ComponentCount=2} }; const int streamOutputVertexSize = 20; //bytes (3 floats for position, 2 floats for texcoord) //output shader SharpShader shaderOutput = new SharpShader(device, "../../HLSL.txt", new SharpShaderDescription() { VertexShaderFunction = "VS_O", GeometryShaderFunction = "GS_O", GeometrySO = soDeclaration }, new InputElement[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0) }); //declare 2 output buffer to switch between them //one will contain the source and the other will be the target of the rendeinrg SharpOutputBuffer outputBufferA = new SharpOutputBuffer(device, 100000); SharpOutputBuffer outputBufferB = new SharpOutputBuffer(device, 100000); //Create constant buffer Buffer11 buffer = shader.CreateBuffer<Matrix>(); //Create texture from file ShaderResourceView texture = ShaderResourceView.FromFile(device.Device, "../../texture.bmp"); fpsCounter.Reset(); //for updating bool update = true; Vector3 nextPosition = new Vector3(); form.KeyUp += (sender, e) => { switch (e.KeyCode) { case Keys.Up: update = true; nextPosition += new Vector3(0, 10, 0); break; case Keys.Down: update = true; nextPosition += new Vector3(0, -10, 0); break; case Keys.A: update = true; nextPosition += new Vector3(-10, 0, 0); break; case Keys.D: update = true; nextPosition += new Vector3(10, 0, 0); break; case Keys.W: update = true; nextPosition += new Vector3(0, 0, 10); break; case Keys.S: update = true; nextPosition += new Vector3(0, 0, -10); break; } }; //main loop RenderLoop.Run(form, () => { //Resizing if (device.MustResize) { device.Resize(); font.Resize(); } //apply states device.UpdateAllStates(); //clear color device.Clear(Color.CornflowerBlue); //apply constant buffer to shader device.DeviceContext.VertexShader.SetConstantBuffer(0, buffer); //set texture device.DeviceContext.PixelShader.SetShaderResource(0, texture); //update output buffer only when needed if (update) { //switch buffer var t = outputBufferA; outputBufferA = outputBufferB; outputBufferB = t; //apply shader shaderOutput.Apply(); //start drawing on output buffer outputBufferA.Begin(); //draw the other output buffer as source device.UpdateData<Matrix>(buffer, Matrix.Identity); outputBufferB.Draw(streamOutputVertexSize); //draw the mesh to add it to buffer device.UpdateData<Matrix>(buffer, Matrix.Translation(nextPosition)); //draw mesh mesh.Draw(); //end rendering on buffer outputBufferA.End(); //stop updating update = false; } //set transformation matrix float ratio = (float)form.ClientRectangle.Width / (float)form.ClientRectangle.Height; Matrix projection = Matrix.PerspectiveFovLH(3.14F / 3.0F, ratio, 1, 1000); Matrix view = Matrix.LookAtLH(new Vector3(0, 50, -100), new Vector3(), Vector3.UnitY); Matrix world = Matrix.Identity; Matrix WVP = world * view * projection; device.UpdateData<Matrix>(buffer, WVP); //stream shader.Apply(); //draw all buffer every frame outputBufferA.Draw(streamOutputVertexSize); //begin drawing text font.Begin(); //draw string fpsCounter.Update(); font.DrawString("FPS: " + fpsCounter.FPS, 0, 0, Color.White); font.DrawString("Press WASD, Up, Down to move cube", 0, 30, Color.White); //flush text to view font.End(); //present device.Present(); }); //release resource font.Dispose(); mesh.Dispose(); buffer.Dispose(); texture.Dispose(); } }
internal static unsafe void Init() { var soElements = new StreamOutputElement[2]; soElements[0].Stream = 0; soElements[0].SemanticName = "TEXCOORD"; soElements[0].SemanticIndex = 0; soElements[0].ComponentCount = 3; soElements[0].OutputSlot = 0; soElements[1].Stream = 0; soElements[1].SemanticName = "TEXCOORD"; soElements[1].SemanticIndex = 1; soElements[1].ComponentCount = 1; soElements[1].OutputSlot = 0; var soStrides = new int[] { sizeof(Vector3) + sizeof(uint) }; m_gs = MyShaders.CreateGs("passes/foliage_streaming/geometry_stage.hlsl", "gs", "", new MyShaderStreamOutputInfo { Elements = soElements, Strides = soStrides, RasterizerStreams = GeometryShader.StreamOutputNoRasterizedStream }); m_instance.SetImmediate(true); }