/// <summary> /// Draws indexed, instanced geometry. /// </summary> /// <param name="primType">Type of the primitives to draw.</param> /// <param name="indexCountPerInstance">Number of indices per instance to draw.</param> /// <param name="startIndex">Starting index in the index buffer at which to read vertex indices from.</param> /// <param name="baseVertex">Offset to add to each vertex index in the index buffer.</param> /// <param name="instanceCount">Number of instances to draw.</param> public override void DrawIndexedInstanced(PrimitiveType primType, int indexCountPerInstance, int startIndex, int baseVertex, int instanceCount) { D3D10Helper.CheckDisposed(_graphicsDevice); if (indexCountPerInstance <= 0) { throw new ArgumentOutOfRangeException("vertexCount", "Index count must be greater than zero."); } if (instanceCount <= 0) { throw new ArgumentOutOfRangeException("instanceCount", "Number of instances to draw must be greater than zero."); } if (_currentIndexBuffer == null) { throw new ArgumentNullException("DrawIndexedInstanced requires a valid index buffer."); } else { D3D10Helper.CheckDisposed(_currentIndexBuffer); } //Send any remaining texture/sampler changes to the device. FlushStates(); _graphicsDevice.InputAssembler.SetInputLayout(_currentPass.InputLayoutMap.GetOrCreateLayout(_currentVertexBuffers, _currentVertexBufferCount)); _graphicsDevice.InputAssembler.SetPrimitiveTopology(D3D10Helper.ToD3DPrimitiveType(primType)); _graphicsDevice.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndex, startIndex, 0); }
/// <summary> /// Gets or sets the sampler state. /// </summary> /// <returns>The sampler state currently set on the device</returns> public SamplerState this[int index] { get { if (index < 0 || index >= _maxSamplers) { throw new ArgumentOutOfRangeException("index", "Index is out of range"); } D3D10Helper.CheckDisposed(_graphicsDevice); return(_samplers[index]); } set { if (index < 0 || index >= _maxSamplers) { throw new ArgumentOutOfRangeException("index", "Index is out of range"); } D3D10Helper.CheckDisposed(_graphicsDevice); SamplerState oldState = _samplers[index]; //Filter out duplicates if (oldState == null) { _samplers[index] = value; _dirtyMark[index] = true; _shortCircuitUpdate = true; } else if (oldState.RenderStateKey != value.RenderStateKey) { _samplers[index] = value; _dirtyMark[index] = true; _shortCircuitUpdate = true; } } }
private void GenerateTargetMips() { for (int i = 0; i < _targetsToMipMapCount; i++) { RenderTargetBinding binding = _targetsToMipMap[i]; //Gen cube mips if (binding.IsRenderTargetCube) { RenderTargetCube rcube = binding.RenderTargetCube; D3D10Helper.CheckDisposed(rcube); if (rcube.MipCount > 1) { D3D10TextureCubeImplementation impl = rcube.Implementation as D3D10TextureCubeImplementation; _graphicsDevice.GenerateMips(impl.D3D10ShaderResourceView); } //Gen 2D tex mips } else { RenderTarget2D r2d = binding.RenderTarget2D; D3D10Helper.CheckDisposed(r2d); if (r2d.MipCount > 1) { D3D10Texture2DImplementation impl = r2d.Implementation as D3D10Texture2DImplementation; _graphicsDevice.GenerateMips(impl.D3D10ShaderResourceView); } } } }
/// <summary> /// Flushes the collection's state to the device, only textures that have been /// changed since the last draw call will get sent. /// </summary> internal void FlushState() { //Return if we haven't even touched these states, so we don't have to loop over them. if (!_shortCircuitUpdate) { return; } for (int i = 0; i < _maxTextures; i++) { //If state is dirty, grab the contents and send to the device if (_dirtyMark[i]) { //Clear the dirty bit _dirtyMark[i] = false; D3D.ShaderResourceView shaderResource = null; Texture value = _textures[i]; //Get shader resource if (value != null) { D3D10Helper.CheckDisposed(value); switch (value.Dimensions) { case TextureDimensions.One: D3D10Texture1DImplementation impl1D = value.Implementation as D3D10Texture1DImplementation; shaderResource = impl1D.D3D10ShaderResourceView; break; case TextureDimensions.Two: D3D10Texture2DImplementation impl2D = value.Implementation as D3D10Texture2DImplementation; shaderResource = impl2D.D3D10ShaderResourceView; break; case TextureDimensions.Three: D3D10Texture3DImplementation impl3D = value.Implementation as D3D10Texture3DImplementation; shaderResource = impl3D.D3D10ShaderResourceView; break; case TextureDimensions.Cube: D3D10TextureCubeImplementation implCube = value.Implementation as D3D10TextureCubeImplementation; shaderResource = implCube.D3D10ShaderResourceView; break; } } //Set shader resource (or null) if (_vertexTex) { _graphicsDevice.VertexShader.SetShaderResource(shaderResource, i); } else { _graphicsDevice.PixelShader.SetShaderResource(shaderResource, i); } } } _shortCircuitUpdate = false; }
/// <summary> /// Sets the index buffer. /// </summary> /// <param name="ib">The ib.</param> public override void SetIndexBuffer(IndexBuffer ib) { _currentIndexBuffer = ib; if (ib != null) { D3D10Helper.CheckDisposed(ib); D3D10IndexBufferImplementation impl = (D3D10IndexBufferImplementation)ib.Implementation; _graphicsDevice.InputAssembler.SetIndexBuffer(impl.D3DIndexBuffer, impl.D3DIndexFormat, 0); } }
private D3D.InputElement GenerateInputElement(VertexElement element, int streamIndex, int instanceFrequency) { return(new D3D.InputElement(D3D10Helper.ToD3DVertexSemantic(element.SemanticName), element.SemanticIndex, D3D10Helper.ToD3DVertexFormat(element.Format), element.Offset, streamIndex, (instanceFrequency > 0) ? D3D.InputClassification.PerInstanceData : D3D.InputClassification.PerVertexData, instanceFrequency)); }
private bool CheckSurfaceFormat(SurfaceFormat surfaceFormat, int sampleCount) { DXGI.Format format = D3D10Helper.ToD3DSurfaceFormat(surfaceFormat); D3D.FormatSupport support = _graphicsDevice.CheckFormatSupport(format); if (sampleCount > 0) { bool correctSamples = CheckMultiSampleQuality(format, sampleCount); return(correctSamples && ((support & D3D.FormatSupport.RenderTarget) == D3D.FormatSupport.RenderTarget) && ((support & D3D.FormatSupport.FormatMultisampleRenderTargetSupport) == D3D.FormatSupport.FormatMultisampleRenderTargetSupport)); } return((support & D3D.FormatSupport.RenderTarget) == D3D.FormatSupport.RenderTarget); }
/// <summary> /// Draws non-indexed geometry. /// </summary> /// <param name="primType">Type of the primitives to draw</param> /// <param name="vertexCount">Number of vertices to draw</param> /// <param name="startVertex">Starting index in the vertex buffer at which to read vertices from.</param> public override void Draw(PrimitiveType primType, int vertexCount, int startVertex) { D3D10Helper.CheckDisposed(_graphicsDevice); if (vertexCount <= 0) { throw new ArgumentOutOfRangeException("vertexCount", "Vertex count must be greater than zero."); } //Send any remaining texture/sampler changes to the device. FlushStates(); _graphicsDevice.InputAssembler.SetInputLayout(_currentPass.InputLayoutMap.GetOrCreateLayout(_currentVertexBuffers, _currentVertexBufferCount)); _graphicsDevice.InputAssembler.SetPrimitiveTopology(D3D10Helper.ToD3DPrimitiveType(primType)); _graphicsDevice.Draw(vertexCount, startVertex); }
internal static D3D.InputElement[] ToD3DInputElements(VertexElement[] elements) { D3D.InputElement[] inputs = new D3D.InputElement[elements.Length]; for (int i = 0; i < elements.Length; i++) { VertexElement element = elements[i]; inputs[i] = new D3D.InputElement(ToD3DVertexSemantic(element.SemanticName), element.SemanticIndex, D3D10Helper.ToD3DVertexFormat(element.Format), element.Offset, 0, 0, 0); } return(inputs); }
private bool CheckDepthFormat(DepthFormat depthFormat, int sampleCount) { if (depthFormat == DepthFormat.None) { return(true); } DXGI.Format format = D3D10Helper.ToD3DDepthFormat(depthFormat); D3D.FormatSupport support = _graphicsDevice.CheckFormatSupport(format); if (sampleCount > 0) { bool correctSamples = CheckMultiSampleQuality(format, sampleCount); return(correctSamples && ((support & D3D.FormatSupport.DepthStencil) == D3D.FormatSupport.DepthStencil) && ((support & D3D.FormatSupport.FormatMultisampleRenderTargetSupport) == D3D.FormatSupport.FormatMultisampleRenderTargetSupport)); } return((support & D3D.FormatSupport.DepthStencil) == D3D.FormatSupport.DepthStencil); }
private static VertexElement CreateVertexElement(D3D.ShaderParameterDescription desc, ref int offset) { D3DC.RegisterComponentType compType = desc.ComponentType; D3DC.RegisterComponentMaskFlags components = desc.UsageMask; String semanticName = desc.SemanticName; uint semanticIndex = desc.SemanticIndex; if (D3D10Helper.IsFlagSet((int)components, (int)D3DC.RegisterComponentMaskFlags.All)) { if (semanticName.Equals("COLOR")) { VertexElement element = new VertexElement(VertexSemantic.Color, (int)semanticIndex, VertexFormat.Color, offset); offset += 4; return(element); } else { VertexElement element = new VertexElement(D3D10Helper.FromD3DVertexSemantic(semanticName), (int)semanticIndex, VertexFormat.Vector4, offset); offset += 16; return(element); } } else if (D3D10Helper.IsFlagSet((int)components, (int)(D3DC.RegisterComponentMaskFlags.ComponentX | D3DC.RegisterComponentMaskFlags.ComponentY | D3DC.RegisterComponentMaskFlags.ComponentZ))) { VertexElement element = new VertexElement(D3D10Helper.FromD3DVertexSemantic(semanticName), (int)semanticIndex, VertexFormat.Vector3, offset); offset += 12; return(element); } else if (D3D10Helper.IsFlagSet((int)components, (int)(D3DC.RegisterComponentMaskFlags.ComponentX | D3DC.RegisterComponentMaskFlags.ComponentY))) { VertexElement element = new VertexElement(D3D10Helper.FromD3DVertexSemantic(semanticName), (int)semanticIndex, VertexFormat.Vector2, offset); offset += 8; return(element); } else if (D3D10Helper.IsFlagSet((int)components, (int)(D3DC.RegisterComponentMaskFlags.ComponentX))) { VertexElement element = new VertexElement(D3D10Helper.FromD3DVertexSemantic(semanticName), (int)semanticIndex, VertexFormat.Single, offset); offset += 4; return(element); } throw new ArgumentException("Invalid vertex element"); }
/// <summary> /// Queries if the specified surface format is valid for texture resources. /// </summary> /// <param name="surfaceFormat">Surface format</param> /// <param name="texType">The texture type</param> /// <returns>True if valid, false otherwise</returns> public bool QueryTextureFormat(SurfaceFormat surfaceFormat, TextureDimensions texType) { DXGI.Format format = D3D10Helper.ToD3DSurfaceFormat(surfaceFormat); D3D.FormatSupport support = _graphicsDevice.CheckFormatSupport(format); switch (texType) { case TextureDimensions.One: return((support & D3D.FormatSupport.Texture1D) == D3D.FormatSupport.Texture1D); case TextureDimensions.Two: return((support & D3D.FormatSupport.Texture2D) == D3D.FormatSupport.Texture2D); case TextureDimensions.Three: return((support & D3D.FormatSupport.Texture3D) == D3D.FormatSupport.Texture3D); case TextureDimensions.Cube: return((support & D3D.FormatSupport.TextureCube) == D3D.FormatSupport.TextureCube); } return(false); }
/// <summary> /// Gets or sets the <see cref="Tesla.Graphics.Texture"/> at the specified index. /// </summary> public Texture this[int index] { get { if (index < 0 || index >= _maxTextures) { throw new ArgumentOutOfRangeException("index", "Index is out of range"); } D3D10Helper.CheckDisposed(_graphicsDevice); return(_textures[index]); } set { if (index < 0 || index >= _maxTextures) { throw new ArgumentOutOfRangeException("index", "Index is out of range"); } D3D10Helper.CheckDisposed(_graphicsDevice); _textures[index] = value; _dirtyMark[index] = true; _shortCircuitUpdate = true; } }
private void SetVertexBuffers(VertexBufferBinding[] vertexBuffers, int vbCount) { //Do some quick validation first D3D10Helper.CheckDisposed(_graphicsDevice); if (vbCount > _adapter.MaximumVertexStreams || vbCount > vertexBuffers.Length) { throw new ArgumentOutOfRangeException("vertexBuffers", "Number of vertex buffers to bind to the device exceeds the maximum number of streams."); } //Clear the currently bound set of buffers Array.Clear(_currentVertexBuffers, 0, _currentVertexBufferCount); Array.Clear(_vertexBindings, 0, _currentVertexBufferCount); _currentVertexBufferCount = 0; //Iterate over each buffer, check if it's valid and add it to the bindings array for (int i = 0; i < vbCount; i++) { VertexBufferBinding binding = vertexBuffers[i]; VertexBuffer vb = binding.VertexBuffer; //Ensure the buffer exists D3D10Helper.CheckDisposed(vb); _currentVertexBuffers[_currentVertexBufferCount] = binding; D3D10VertexBufferImplementation impl = (D3D10VertexBufferImplementation)vb.Implementation; _vertexBindings[_currentVertexBufferCount] = new D3D.VertexBufferBinding(impl.D3DVertexBuffer, vb.VertexDeclaration.VertexStride, binding.VertexOffset); _currentVertexBufferCount++; } //Set the D3D10 bindings to the device if (vbCount == 1) { _graphicsDevice.InputAssembler.SetVertexBuffers(0, _vertexBindings[0]); } else { _graphicsDevice.InputAssembler.SetVertexBuffers(0, _vertexBindings); } }
private void SetBackBufferTargets() { if (_activeBackBuffer != null) { D3D10Helper.CheckDisposed(_activeBackBuffer); D3D.RenderTargetView rtv = _activeBackBuffer.D3D10RenderTargetView; D3D.DepthStencilView dsv = _activeBackBuffer.D3D10DepthStencilView; if (rtv != null) { if (dsv != null) { _graphicsDevice.OutputMerger.SetTargets(dsv, rtv); } else { _graphicsDevice.OutputMerger.SetTargets(rtv); } } } }
/// <summary> /// Queries for the number of multisample quality levels are supported for the sample count. /// </summary> /// <param name="format">Specified format</param> /// <param name="multiSamplecount">Sample count</param> /// <returns>Number of supported quality levels </returns> public int QueryMultiSampleQualityLevels(SurfaceFormat format, int multiSamplecount) { return(_graphicsDevice.CheckMultisampleQualityLevels(D3D10Helper.ToD3DSurfaceFormat(format), multiSamplecount)); }
public void SetRenderTargets(RenderTargetBinding[] targets) { D3D10Helper.CheckDisposed(_graphicsDevice); if (targets == null || targets.Length == 0) { //Clear targets ClearTargets(); //Set the swapchain's targets to the device, unbinding the current ones SetBackBufferTargets(); //Generate mip maps of previously bounded targets GenerateTargetMips(); } else { //If we have a larger array than the max targets possible, throw an exception if (targets.Length > _currentRenderTargets.Length) { throw new ArgumentOutOfRangeException("Cannot bind more than 8 targets at a time."); } //Clear targets ClearTargets(); D3D.RenderTargetView rtv; D3D.DepthStencilView dsv = null; DepthFormat depthFormat = DepthFormat.None; int width = 0; int height = 0; int samples = 0; int pixelDepth = 0; for (int i = 0; i < targets.Length; i++) { RenderTargetBinding binding = targets[i]; RenderTargetUsage usage = RenderTargetUsage.DiscardContents; if (binding.IsRenderTargetCube) { D3D10TextureCubeImplementation cubeImpl = binding.RenderTargetCube.Implementation as D3D10TextureCubeImplementation; D3D10Helper.CheckDisposed(cubeImpl); rtv = cubeImpl.GetRenderTargetView(binding.CubeMapFace); usage = cubeImpl.TargetUsage; if (i == 0) { width = cubeImpl.Size; height = cubeImpl.Size; dsv = cubeImpl.D3D10DepthStencilView; depthFormat = cubeImpl.DepthFormat; samples = cubeImpl.MultiSampleCount; pixelDepth = D3D10Helper.FormatSize(cubeImpl.Format); } else { if (cubeImpl.Size != width || cubeImpl.Size != height || cubeImpl.MultiSampleCount != samples || D3D10Helper.FormatSize(cubeImpl.Format) != pixelDepth) { throw new ArgumentException("All render target dimensions must match."); } } } else { D3D10Texture2DImplementation texImpl = binding.RenderTarget2D.Implementation as D3D10Texture2DImplementation; D3D10Helper.CheckDisposed(texImpl); rtv = texImpl.D3D10RenderTargetVew; usage = texImpl.TargetUsage; if (i == 0) { width = texImpl.Width; height = texImpl.Height; dsv = texImpl.D3D10DepthStencilView; depthFormat = texImpl.DepthFormat; samples = texImpl.MultiSampleCount; pixelDepth = D3D10Helper.FormatSize(texImpl.Format); } else { if (texImpl.Width != width || texImpl.Height != height || texImpl.MultiSampleCount != samples || D3D10Helper.FormatSize(texImpl.Format) != pixelDepth) { throw new ArgumentException("All render target dimensions, sample count, and bit depth must match."); } } } //Set the targets to the arrays, after we're done processing we set them all at once _currentRenderTargets[i] = binding; _views[i] = rtv; _currentRenderTargetCount++; //Check usage, if we're using a target that isn't preserve contents, //then we clear the target. if (usage != RenderTargetUsage.PreserveContents) { _graphicsDevice.ClearRenderTargetView(rtv, new SlimDX.Color4(1.0f, 0, 0, 0)); if (i == 0 && dsv != null) { D3D.DepthStencilClearFlags flags = D3D.DepthStencilClearFlags.Depth; if (depthFormat == DepthFormat.Depth24Stencil8) { flags |= D3D.DepthStencilClearFlags.Stencil; } _graphicsDevice.ClearDepthStencilView(dsv, flags, 1.0f, 0); } } } //Bind targets if (dsv != null) { _graphicsDevice.OutputMerger.SetTargets(dsv, _views); } else { _graphicsDevice.OutputMerger.SetTargets(_views); } //Generate mip maps of previously bounded targets GenerateTargetMips(); //Note: What if a user binds a target here that was previously bound, //is generating mip maps on a bound target ok? I don't know if //a user would even want to do that... } }
/// <summary> /// Clears the active targets, or back buffer if there are none. /// </summary> /// <param name="options"></param> /// <param name="color"></param> /// <param name="depth"></param> /// <param name="stencil"></param> public void ClearTargets(ClearOptions options, Color color, float depth, int stencil) { D3D10Helper.CheckDisposed(_graphicsDevice); SlimDX.Color4 sc; D3D10Helper.Convert(ref color, out sc); if (_currentRenderTargetCount == 0 && _activeBackBuffer != null) { D3D10Helper.CheckDisposed(_activeBackBuffer); if (_activeBackBuffer.D3D10DepthStencilView != null) { if (((options & ClearOptions.Depth) == ClearOptions.Depth) && ((options & ClearOptions.Stencil) == ClearOptions.Stencil)) { _graphicsDevice.ClearDepthStencilView(_activeBackBuffer.D3D10DepthStencilView, D3D.DepthStencilClearFlags.Depth | D3D.DepthStencilClearFlags.Stencil, depth, (byte)stencil); } else if ((options & ClearOptions.Depth) == ClearOptions.Depth) { _graphicsDevice.ClearDepthStencilView(_activeBackBuffer.D3D10DepthStencilView, D3D.DepthStencilClearFlags.Depth, depth, (byte)stencil); } else if ((options & ClearOptions.Stencil) == ClearOptions.Stencil) { _graphicsDevice.ClearDepthStencilView(_activeBackBuffer.D3D10DepthStencilView, D3D.DepthStencilClearFlags.Stencil, depth, (byte)stencil); } } if ((_activeBackBuffer.D3D10RenderTargetView != null) && ((options & ClearOptions.Target) == ClearOptions.Target)) { _graphicsDevice.ClearRenderTargetView(_activeBackBuffer.D3D10RenderTargetView, sc); } } else { for (int i = 0; i < _currentRenderTargetCount; i++) { RenderTargetBinding binding = _currentRenderTargets[i]; D3D.DepthStencilView dsv = null; D3D.RenderTargetView rtv = null; if (!binding.IsRenderTargetCube) { D3D10Texture2DImplementation impl2D = binding.RenderTarget2D.Implementation as D3D10Texture2DImplementation; D3D10Helper.CheckDisposed(impl2D); dsv = impl2D.D3D10DepthStencilView; rtv = impl2D.D3D10RenderTargetVew; } else { D3D10TextureCubeImplementation implcube = binding.RenderTargetCube.Implementation as D3D10TextureCubeImplementation; D3D10Helper.CheckDisposed(implcube); dsv = implcube.D3D10DepthStencilView; rtv = implcube.GetRenderTargetView(binding.CubeMapFace); } if (dsv != null) { if (((options & ClearOptions.Depth) == ClearOptions.Depth) && ((options & ClearOptions.Stencil) == ClearOptions.Stencil)) { _graphicsDevice.ClearDepthStencilView(dsv, D3D.DepthStencilClearFlags.Depth | D3D.DepthStencilClearFlags.Stencil, depth, (byte)stencil); } else if ((options & ClearOptions.Depth) == ClearOptions.Depth) { _graphicsDevice.ClearDepthStencilView(dsv, D3D.DepthStencilClearFlags.Depth, depth, (byte)stencil); } else if ((options & ClearOptions.Stencil) == ClearOptions.Stencil) { _graphicsDevice.ClearDepthStencilView(dsv, D3D.DepthStencilClearFlags.Stencil, depth, (byte)stencil); } } if ((rtv != null) && ((options & ClearOptions.Target) == ClearOptions.Target)) { _graphicsDevice.ClearRenderTargetView(rtv, sc); } } } }
/// <summary> /// Initializes a new instance of the <see cref="D3D10GraphicsAdapter"/> class. /// </summary> /// <param name="graphicsDevice">The graphics device.</param> /// <param name="factory">The DXGI factory.</param> /// <param name="adapterIndex">Index of the adapter.</param> internal D3D10GraphicsAdapter(D3D.Device graphicsDevice, DXGI.Factory factory, int adapterIndex) { _graphicsDevice = graphicsDevice; _adapterIndex = adapterIndex; List <DisplayMode> modes = new List <DisplayMode>(); DXGI.Adapter adapter = factory.GetAdapter(adapterIndex); if (adapter != null) { DXGI.AdapterDescription adDesc = adapter.Description; _desc = adDesc.Description; _devId = adDesc.DeviceId; _rev = adDesc.Revision; _subsystemId = adDesc.SubsystemId; _vendorId = adDesc.VendorId; DXGI.Output output = adapter.GetOutput(0); if (output != null) { foreach (SurfaceFormat format in Enum.GetValues(typeof(SurfaceFormat))) { try { System.Collections.ObjectModel.ReadOnlyCollection <DXGI.ModeDescription> modeList = output.GetDisplayModeList(D3D10Helper.ToD3DSurfaceFormat(format), 0); if (modeList == null) { continue; } foreach (DXGI.ModeDescription modeDesc in modeList) { DisplayMode displayMode = new DisplayMode(modeDesc.Width, modeDesc.Height, format); if (!modes.Contains(displayMode)) { modes.Add(displayMode); } } } catch (Exception e) { String s = e.StackTrace; continue; } } _displayModes = new DisplayModeCollection(modes); output.Dispose(); } adapter.Dispose(); } }