private static Texture DecodeMultiframe(ImagingFactory imagingFactory, WicFlags flags, TextureDescription description, BitmapDecoder decoder) { var texture = new Texture(description); Guid dstFormat = ToWic(description.Format, false); for (int index = 0; index < description.ArraySize; ++index) { var image = texture.Images[index]; using (var frame = decoder.GetFrame(index)) { var pfGuid = frame.PixelFormat; var size = frame.Size; if (size.Width == description.Width && size.Height == description.Height) { // This frame does not need resized if (pfGuid == dstFormat) { frame.CopyPixels(image.Data, image.RowPitch); } else { using (var converter = new FormatConverter(imagingFactory)) { converter.Initialize(frame, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); converter.CopyPixels(image.Data, image.RowPitch); } } } else { // This frame needs resizing using (var scaler = new BitmapScaler(imagingFactory)) { scaler.Initialize(frame, description.Width, description.Height, GetWicInterp(flags)); Guid pfScaler = scaler.PixelFormat; if (pfScaler == dstFormat) { scaler.CopyPixels(image.Data, image.RowPitch); } else { // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we // convert it to our desired format using (var converter = new FormatConverter(imagingFactory)) { converter.Initialize(scaler, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); converter.CopyPixels(image.Data, image.RowPitch); } } } } } } return texture; }
/// <summary> /// Initializes a new <see cref="Texture"/> from the specified <see cref="TextureDescription"/>. /// </summary> /// <param name="description">The <see cref="TextureDescription"/> to initialize from.</param> protected Texture(TextureDescription description) { Contract.Requires<ArgumentNullException>(description != null); Contract.Requires<ArgumentException>(Enum.IsDefined(typeof(TextureTarget), description.Target)); this.Description = description; this.VerifyAccess(); using (this.Bind(0)) { // Set anisotropic filtering level and min and mag filter int linearMipmapLinear = Texture.linearMipmapLinear; int linear = Texture.linear; GL.TexParameterI(this.Target, TextureParameterName.TextureMinFilter, ref linearMipmapLinear); GL.TexParameterI(this.Target, TextureParameterName.TextureMagFilter, ref linear); if (VideoSettings.Default.AnisotropicFiltering && SupportsExtension("GL_EXT_texture_filter_anisotropic")) { // User might want higher aniso level than the h/w supports. float requestedAnisoLevel = VideoSettings.Default.AnisotropicLevel; float maxSupportedAnisoLevel = GL.GetFloat((GetPName)OpenTK.Graphics.OpenGL.ExtTextureFilterAnisotropic.MaxTextureMaxAnisotropyExt); GL.TexParameter(this.Target, anisoParameterName, Math.Min(requestedAnisoLevel, maxSupportedAnisoLevel)); } GL.GenerateMipmap((GenerateMipmapTarget)this.Target); } }
public async Task<object> ReadAsync(ContentReadParameters parameters) { using (Bitmap bmp = new Bitmap(parameters.AssetStream)) { BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, GDIPixelFormat.Format32bppArgb); try { return await this.Dispatcher.Invoke((Func<CancellationToken, object>)(ct => { ct.ThrowIfCancellationRequested(); TextureDescription desc = new TextureDescription( data.Width, data.Height, TextureDescription.GetMaxTextureLevels(data.Width, data.Height), 2, (TextureTarget2d)(parameters.Parameter ?? TextureTarget2d.Texture2D), PixelInternalFormat.Rgba ); if (parameters.AssetType == typeof(Texture2D)) { return Texture2D.Create(desc, data.Scan0, GLPixelFormat.Bgra, PixelType.UnsignedByte, data.Width, data.Height, 0, 0, 0); } else if (parameters.AssetType == typeof(Texture1DArray)) { return Texture1DArray.Create(desc, data.Scan0, GLPixelFormat.Bgra, PixelType.UnsignedByte, data.Width, data.Height, 0, 0, 0); } else { throw new InvalidOperationException( string.Format( "{0} can only load {1} and {2}, not {3}!", typeof(TextureReader).Name, typeof(Texture1DArray).Name, typeof(Texture2D).Name, parameters.AssetType.Name ) ); } }), DispatcherPriority.Normal, parameters.CancellationToken).ConfigureAwait(false); } finally { bmp.UnlockBits(data); } } }
private static TextureDescription New1D(int width, PixelFormat format, TextureFlags flags, int mipCount, int arraySize, GraphicsResourceUsage usage) { usage = (flags & TextureFlags.UnorderedAccess) != 0 ? GraphicsResourceUsage.Default : usage; var desc = new TextureDescription() { Dimension = TextureDimension.Texture1D, Width = width, Height = 1, Depth = 1, ArraySize = arraySize, Flags = flags, Format = format, MipLevels = Texture.CalculateMipMapCount(mipCount, width), Usage = Texture.GetUsageWithFlags(usage, flags), }; return desc; }
private static TextureDescription New3D(int width, int height, int depth, PixelFormat format, TextureFlags flags, int mipCount, GraphicsResourceUsage usage) { var desc = new TextureDescription() { Width = width, Height = height, Depth = depth, Flags = flags, Format = format, MipLevels = Texture.CalculateMipMapCount(mipCount, width, height, depth), Usage = Texture.GetUsageWithFlags(usage, flags), ArraySize = 1, Dimension = TextureDimension.Texture3D, MultiSampleLevel = MSAALevel.None }; return desc; }
private static TextureDescription New2D(int width, int height, PixelFormat format, TextureFlags textureFlags, int mipCount, int arraySize, GraphicsResourceUsage usage) { if ((textureFlags & TextureFlags.UnorderedAccess) != 0) usage = GraphicsResourceUsage.Default; var desc = new TextureDescription() { Dimension = TextureDimension.Texture2D, Width = width, Height = height, Depth = 1, ArraySize = arraySize, MultiSampleLevel = MSAALevel.None, Flags = textureFlags, Format = format, MipLevels = Texture.CalculateMipMapCount(mipCount, width, height), Usage = Texture.GetUsageWithFlags(usage, textureFlags), }; return desc; }
protected override void DrawCore(RenderContext context, RenderDrawContext drawContext) { if (!IsIncrustEnabled) { return; } using (context.PushRenderViewAndRestore(RenderView)) using (drawContext.PushTagAndRestore(CameraComponentRendererExtensions.Current, Camera)) { var oldViewport = drawContext.CommandList.Viewport; // Allocate a RT for the incrust GeneratedIncrust = drawContext.GraphicsContext.Allocator.GetTemporaryTexture2D(TextureDescription.New2D((int)Viewport.Width, (int)Viewport.Height, 1, drawContext.CommandList.RenderTarget.Format, TextureFlags.ShaderResource | TextureFlags.RenderTarget)); var depthBuffer = drawContext.CommandList.DepthStencilBuffer != null?drawContext.GraphicsContext.Allocator.GetTemporaryTexture2D(TextureDescription.New2D((int)Viewport.Width, (int)Viewport.Height, 1, drawContext.CommandList.DepthStencilBuffer.Format, TextureFlags.DepthStencil)) : null; // Push and set render target using (drawContext.PushRenderTargetsAndRestore()) { drawContext.CommandList.SetRenderTarget(depthBuffer, GeneratedIncrust); drawContext.CommandList.SetViewport(Viewport); Content.Draw(drawContext); drawContext.CommandList.SetViewport(oldViewport); } // Note: GeneratedIncrust is released by RenderIncrustCompositorPart if (depthBuffer != null) { drawContext.GraphicsContext.Allocator.ReleaseReference(depthBuffer); } } }
protected override Texture CreateTextureCore(ref TextureDescription description) { return(new D3D11Texture(_device, ref description)); }
private void StreamingTask(int residency) { if (cancellationToken.IsCancellationRequested) { return; } // Cache data var mipsChange = residency - CurrentResidency; var mipsCount = residency; Debug.Assert(mipsChange != 0, $"mipsChange[{mipsChange}] != 0"); if (residency == 0) { // Release Manager.RegisterMemoryUsage(-texture.SizeInBytes); texture.ReleaseData(); residentMips = 0; return; } try { Storage.LockChunks(); // Setup texture description TextureDescription newDesc = description; var newHighestResidentMipIndex = TotalMipLevels - mipsCount; newDesc.MipLevels = mipsCount; var topMip = mipInfos[description.MipLevels - newDesc.MipLevels]; newDesc.Width = topMip.Width; newDesc.Height = topMip.Height; // Load chunks var mipsData = new IntPtr[mipsCount]; for (var mipIndex = 0; mipIndex < mipsCount; mipIndex++) { var totalMipIndex = newHighestResidentMipIndex + mipIndex; var chunk = Storage.GetChunk(totalMipIndex); if (chunk == null) { throw new ContentStreamingException("Data chunk is missing.", Storage); } if (chunk.Size != mipInfos[totalMipIndex].TotalSize) { throw new ContentStreamingException("Data chunk has invalid size.", Storage); } var data = chunk.GetData(fileProvider); if (!chunk.IsLoaded) { throw new ContentStreamingException("Data chunk is not loaded.", Storage); } if (cancellationToken.IsCancellationRequested) { return; } mipsData[mipIndex] = data; } // Get data boxes var dataBoxIndex = 0; var dataBoxes = new DataBox[newDesc.MipLevels * newDesc.ArraySize]; for (var arrayIndex = 0; arrayIndex < newDesc.ArraySize; arrayIndex++) { for (var mipIndex = 0; mipIndex < mipsCount; mipIndex++) { var totalMipIndex = newHighestResidentMipIndex + mipIndex; var info = mipInfos[totalMipIndex]; dataBoxes[dataBoxIndex].DataPointer = mipsData[mipIndex] + info.SlicePitch * arrayIndex; dataBoxes[dataBoxIndex].RowPitch = info.RowPitch; dataBoxes[dataBoxIndex].SlicePitch = info.SlicePitch; dataBoxIndex++; } } if (cancellationToken.IsCancellationRequested) { return; } // Create texture (use staging object and swap it on sync) textureToSync = Texture.New(texture.GraphicsDevice, newDesc, new TextureViewDescription(), dataBoxes); textureToSync.FullQualitySize = texture.FullQualitySize; residentMips = newDesc.MipLevels; } finally { Storage.UnlockChunks(); } }
/// <summary> /// Creates a new <see cref="Texture"/>. /// </summary> /// <param name="description">The desired properties of the created object.</param> /// <returns>A new <see cref="Texture"/>.</returns> public Texture CreateTexture(TextureDescription description) => CreateTexture(ref description);
private static Texture CopyImage(BinaryReader reader, TextureDescription description, ComputePitchFlags cpFlags, ConversionFlags convFlags, uint[] pal8) { if (reader == null) throw new ArgumentNullException("reader"); if ((convFlags & ConversionFlags.Expand) != 0) { if ((convFlags & ConversionFlags.Format888) != 0) cpFlags |= ComputePitchFlags.Bpp24; else if ((convFlags & (ConversionFlags.Format565 | ConversionFlags.Format5551 | ConversionFlags.Format4444 | ConversionFlags.Format8332 | ConversionFlags.FormatA8P8 | ConversionFlags.FormatL16 | ConversionFlags.FormatA8L8)) != 0) cpFlags |= ComputePitchFlags.Bpp16; else if ((convFlags & (ConversionFlags.Format44 | ConversionFlags.Format332 | ConversionFlags.Pal8 | ConversionFlags.FormatL8)) != 0) cpFlags |= ComputePitchFlags.Bpp8; } var texture = new Texture(description); description = texture.Description; // MipLevel may have been set. ScanlineFlags tflags = (convFlags & ConversionFlags.NoAlpha) != 0 ? ScanlineFlags.SetAlpha : 0; if ((convFlags & ConversionFlags.Swizzle) != 0) tflags |= ScanlineFlags.Legacy; switch (description.Dimension) { case TextureDimension.Texture1D: case TextureDimension.Texture2D: case TextureDimension.TextureCube: { int index = 0; for (int item = 0; item < description.ArraySize; ++item) { int width = description.Width; int height = description.Height; for (int level = 0; level < description.MipLevels; ++level, ++index) { int sRowPitch, sSlicePitch; TextureHelper.ComputePitch(description.Format, width, height, out sRowPitch, out sSlicePitch, cpFlags); var image = texture.Images[index]; if (TextureHelper.IsBCn(description.Format) || TextureHelper.IsPlanar(description.Format)) { reader.Read(image.Data, 0, image.Data.Length); } else { using (var stream = new MemoryStream(image.Data)) using (var writer = new BinaryWriter(stream)) { for (int h = 0; h < height; ++h) { if ((convFlags & ConversionFlags.Expand) != 0) { if ((convFlags & (ConversionFlags.Format565 | ConversionFlags.Format5551 | ConversionFlags.Format4444)) != 0) { if (!TextureHelper.ExpandScanline(reader, sRowPitch, (convFlags & ConversionFlags.Format565) != 0 ? DataFormat.B5G6R5_UNORM : DataFormat.B5G5R5A1_UNORM, writer, image.RowPitch, DataFormat.R8G8B8A8_UNORM, tflags)) throw new InvalidDataException("Unable to expand format."); } else { LegacyFormat lformat = FindLegacyFormat(convFlags); if (!LegacyExpandScanline(reader, sRowPitch, lformat, writer, image.RowPitch, description.Format, pal8, tflags)) throw new InvalidDataException("Unable to expand legacy format."); } } else if ((convFlags & ConversionFlags.Swizzle) != 0) { TextureHelper.SwizzleScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags); } else { TextureHelper.CopyScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags); } } } } if (width > 1) width >>= 1; if (height > 1) height >>= 1; } } } break; case TextureDimension.Texture3D: { int index = 0; int width = description.Width; int height = description.Height; int depth = description.Depth; for (int level = 0; level < description.MipLevels; ++level) { int sRowPitch, sSlicePitch; TextureHelper.ComputePitch(description.Format, width, height, out sRowPitch, out sSlicePitch, cpFlags); for (int slice = 0; slice < depth; ++slice, ++index) { // We use the same memory organization that Direct3D 11 needs for D3D11_SUBRESOURCE_DATA // with all slices of a given miplevel being continuous in memory var image = texture.Images[index]; if (TextureHelper.IsBCn(description.Format)) { reader.Read(image.Data, 0, image.Data.Length); } else if (TextureHelper.IsPlanar(description.Format)) { // Direct3D does not support any planar formats for Texture3D throw new NotSupportedException("Planar texture formats are not support for volume textures."); } else { using (var stream = new MemoryStream(image.Data)) using (var writer = new BinaryWriter(stream)) { for (int h = 0; h < height; ++h) { if ((convFlags & ConversionFlags.Expand) != 0) { if ((convFlags & (ConversionFlags.Format565 | ConversionFlags.Format5551 | ConversionFlags.Format4444)) != 0) { if (!TextureHelper.ExpandScanline(reader, sRowPitch, (convFlags & ConversionFlags.Format565) != 0 ? DataFormat.B5G6R5_UNORM : DataFormat.B5G5R5A1_UNORM, writer, image.RowPitch, DataFormat.R8G8B8A8_UNORM, tflags)) throw new InvalidDataException("Unable to expand format."); } else { LegacyFormat lformat = FindLegacyFormat(convFlags); if (!LegacyExpandScanline(reader, sRowPitch, lformat, writer, image.RowPitch, description.Format, pal8, tflags)) throw new InvalidDataException("Unable to expand legacy format."); } } else if ((convFlags & ConversionFlags.Swizzle) != 0) { TextureHelper.SwizzleScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags); } else { TextureHelper.CopyScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags); } } } } } if (width > 1) width >>= 1; if (height > 1) height >>= 1; if (depth > 1) depth >>= 1; } } break; default: throw new NotSupportedException("The specified texture dimension is not supported."); } return texture; }
private static void EncodeDDSHeader(BinaryWriter writer, TextureDescription description, DdsFlags flags) { if (!TextureHelper.IsValidDds(description.Format)) throw new ArgumentException("Invalid texture format.", "description"); if (TextureHelper.IsPalettized(description.Format)) throw new NotSupportedException("Palettized texture formats are not supported."); if (description.ArraySize > 1) { if (description.ArraySize != 6 || description.Dimension != TextureDimension.Texture2D || description.Dimension != TextureDimension.TextureCube) { // Texture1D arrays, Texture2D arrays, and TextureCube arrays must be stored using 'DX10' extended header flags |= DdsFlags.ForceDX10Ext; } } if ((flags & DdsFlags.ForceDX10ExtMisc2) != 0) flags |= DdsFlags.ForceDX10Ext; PixelFormat ddpf = default(PixelFormat); if ((flags & DdsFlags.ForceDX10Ext) == 0) { switch (description.Format) { case DataFormat.R8G8B8A8_UNORM: ddpf = PixelFormat.A8B8G8R8; break; case DataFormat.R16G16_UNORM: ddpf = PixelFormat.G16R16; break; case DataFormat.R8G8_UNORM: ddpf = PixelFormat.A8L8; break; case DataFormat.R16_UNORM: ddpf = PixelFormat.L16; break; case DataFormat.R8_UNORM: ddpf = PixelFormat.L8; break; case DataFormat.A8_UNORM: ddpf = PixelFormat.A8; break; case DataFormat.R8G8_B8G8_UNORM: ddpf = PixelFormat.R8G8_B8G8; break; case DataFormat.G8R8_G8B8_UNORM: ddpf = PixelFormat.G8R8_G8B8; break; case DataFormat.BC1_UNORM: ddpf = PixelFormat.DXT1; break; case DataFormat.BC2_UNORM: ddpf = /* (description.AlphaMode == AlphaMode.Premultiplied) ? PixelFormat.DXT2 : */ PixelFormat.DXT3; break; case DataFormat.BC3_UNORM: ddpf = /* (description.AlphaMode == AlphaMode.Premultiplied) ? PixelFormat.DXT2 : */ PixelFormat.DXT5; break; case DataFormat.BC4_UNORM: ddpf = PixelFormat.BC4_UNorm; break; case DataFormat.BC4_SNORM: ddpf = PixelFormat.BC4_SNorm; break; case DataFormat.BC5_UNORM: ddpf = PixelFormat.BC5_UNorm; break; case DataFormat.BC5_SNORM: ddpf = PixelFormat.BC5_SNorm; break; case DataFormat.B5G6R5_UNORM: ddpf = PixelFormat.R5G6B5; break; case DataFormat.B5G5R5A1_UNORM: ddpf = PixelFormat.A1R5G5B5; break; case DataFormat.R8G8_SNORM: ddpf = PixelFormat.V8U8; break; case DataFormat.R8G8B8A8_SNORM: ddpf = PixelFormat.Q8W8V8U8; break; case DataFormat.R16G16_SNORM: ddpf = PixelFormat.V16U16; break; case DataFormat.B8G8R8A8_UNORM: ddpf = PixelFormat.A8R8G8B8; break; // DXGI 1.1 case DataFormat.B8G8R8X8_UNORM: ddpf = PixelFormat.X8R8G8B8; break; // DXGI 1.1 //#if DIRECTX11_1 case DataFormat.B4G4R4A4_UNORM: ddpf = PixelFormat.A4R4G4B4; break; case DataFormat.YUY2: ddpf = PixelFormat.YUY2; break; //#endif // Legacy D3DX formats using D3DFMT enum value as FourCC case DataFormat.R32G32B32A32_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 116; // D3DFMT_A32B32G32R32F break; case DataFormat.R16G16B16A16_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 113; // D3DFMT_A16B16G16R16F break; case DataFormat.R16G16B16A16_UNORM: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 36; // D3DFMT_A16B16G16R16 break; case DataFormat.R16G16B16A16_SNORM: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 110; // D3DFMT_Q16W16V16U16 break; case DataFormat.R32G32_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 115; // D3DFMT_G32R32F break; case DataFormat.R16G16_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 112; // D3DFMT_G16R16F break; case DataFormat.R32_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 114; // D3DFMT_R32F break; case DataFormat.R16_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 111; // D3DFMT_R16F break; } } writer.Write(MagicHeader); var header = new Header(); header.Size = Marshal.SizeOf(typeof(Header)); header.Flags = HeaderFlags.Texture; header.SurfaceFlags = SurfaceFlags.Texture; if (description.MipLevels > 0) { header.Flags |= HeaderFlags.Mipmap; header.MipMapCount = description.MipLevels; if (header.MipMapCount > 1) header.SurfaceFlags |= SurfaceFlags.Mipmap; } switch (description.Dimension) { case TextureDimension.Texture1D: header.Height = description.Height; header.Width = header.Depth = 1; break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: header.Height = description.Height; header.Width = description.Width; header.Depth = 1; if (description.Dimension == TextureDimension.TextureCube) { header.SurfaceFlags |= SurfaceFlags.Cubemap; header.CubemapFlags |= CubemapFlags.AllFaces; } break; case TextureDimension.Texture3D: header.Flags |= HeaderFlags.Volume; header.CubemapFlags |= CubemapFlags.Volume; header.Height = description.Height; header.Width = description.Width; header.Depth = description.Depth; break; default: throw new NotSupportedException("The specified texture dimension is not supported."); } int rowPitch, slicePitch; TextureHelper.ComputePitch(description.Format, description.Width, description.Height, out rowPitch, out slicePitch); if (TextureHelper.IsBCn(description.Format)) { header.Flags |= HeaderFlags.LinearSize; header.PitchOrLinearSize = slicePitch; } else { header.Flags |= HeaderFlags.Pitch; header.PitchOrLinearSize = rowPitch; } if (ddpf.Size != 0) { header.PixelFormat = ddpf; writer.BaseStream.WriteStruct(header); } else { header.PixelFormat = PixelFormat.DX10; var ext = new HeaderDXT10(); ext.DXGIFormat = description.Format; switch (description.Dimension) { case TextureDimension.Texture1D: ext.ResourceDimension = ResourceDimension.Texture1D; break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: ext.ResourceDimension = ResourceDimension.Texture2D; break; case TextureDimension.Texture3D: ext.ResourceDimension = ResourceDimension.Texture3D; break; } if (description.Dimension == TextureDimension.TextureCube) { ext.MiscFlags |= ResourceOptionFlags.TextureCube; ext.ArraySize = description.ArraySize / 6; } else { ext.ArraySize = description.ArraySize; } if ((flags & DdsFlags.ForceDX10ExtMisc2) != 0) { // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0. //ext.MiscFlags2 = description.MiscFlags2; throw new NotImplementedException("DdsFlags.ForceDX10ExtMisc2 is not implemented."); } writer.BaseStream.WriteStruct(header); writer.BaseStream.WriteStruct(ext); } }
/// <summary> /// Gets a render target with the specified description, scoped for the duration of the <see cref="DrawEffect.DrawCore"/>. /// </summary> /// <returns>A new instance of texture.</returns> protected Texture NewScopedRenderTarget2D(TextureDescription description) { // TODO: Check if we should introduce an enum for the kind of scope (per DrawCore, per Frame...etc.) CheckIsInDrawCore(); return(PushScopedResource(Context.Allocator.GetTemporaryTexture2D(description))); }
private static ImageCollection CreateImageCollection(TextureDescription description, bool skipMipLevel0 = false) { int numberOfImages, pixelSize; DetermineImages(description, out numberOfImages, out pixelSize); var images = new ImageCollection(numberOfImages); int index = 0; switch (description.Dimension) { case TextureDimension.Texture1D: case TextureDimension.Texture2D: case TextureDimension.TextureCube: Debug.Assert(description.ArraySize != 0); Debug.Assert(description.MipLevels > 0); for (int item = 0; item < description.ArraySize; item++) { int w = description.Width; int h = description.Height; for (int level = 0; level < description.MipLevels; level++) { if (!skipMipLevel0 || level != 0) images[index] = new Image(w, h, description.Format); index++; if (h > 1) h >>= 1; if (w > 1) w >>= 1; } } break; case TextureDimension.Texture3D: { Debug.Assert(description.MipLevels > 0); Debug.Assert(description.Depth > 0); int w = description.Width; int h = description.Height; int d = description.Depth; for (int level = 0; level < description.MipLevels; level++) { for (int slice = 0; slice < d; slice++) { // We use the same memory organization that Direct3D 11 needs for D3D11_SUBRESOURCE_DATA // with all slices of a given mip level being continuous in memory. if (!skipMipLevel0 || level != 0) images[index] = new Image(w, h, description.Format); index++; } if (h > 1) h >>= 1; if (w > 1) w >>= 1; if (d > 1) d >>= 1; } } break; default: Debug.Fail("Unexpected texture dimension"); break; } return images; }
public D3D11Texture(Device device, ref TextureDescription description) { Width = description.Width; Height = description.Height; Depth = description.Depth; MipLevels = description.MipLevels; ArrayLayers = description.ArrayLayers; Format = description.Format; Usage = description.Usage; SampleCount = description.SampleCount; DxgiFormat = D3D11Formats.ToDxgiFormat( description.Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil); CpuAccessFlags cpuFlags = CpuAccessFlags.None; ResourceUsage resourceUsage = ResourceUsage.Default; BindFlags bindFlags = BindFlags.None; if ((description.Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget) { bindFlags |= BindFlags.RenderTarget; } if ((description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil) { bindFlags |= BindFlags.DepthStencil; } if ((description.Usage & TextureUsage.Sampled) == TextureUsage.Sampled) { bindFlags |= BindFlags.ShaderResource; } if ((description.Usage & TextureUsage.Storage) == TextureUsage.Storage) { bindFlags |= BindFlags.UnorderedAccess; } if ((description.Usage & TextureUsage.Staging) == TextureUsage.Staging) { cpuFlags = CpuAccessFlags.Read | CpuAccessFlags.Write; resourceUsage = ResourceUsage.Staging; } ResourceOptionFlags optionFlags = ResourceOptionFlags.None; int arraySize = (int)description.ArrayLayers; if ((description.Usage & TextureUsage.Cubemap) == TextureUsage.Cubemap) { optionFlags = ResourceOptionFlags.TextureCube; arraySize *= 6; } Texture2DDescription deviceDescription = new Texture2DDescription() { Width = (int)description.Width, Height = (int)description.Height, MipLevels = (int)description.MipLevels, ArraySize = arraySize, Format = DxgiFormat, BindFlags = bindFlags, CpuAccessFlags = cpuFlags, Usage = resourceUsage, SampleDescription = new SharpDX.DXGI.SampleDescription((int)FormatHelpers.GetSampleCountUInt32(SampleCount), 0), OptionFlags = optionFlags, }; DeviceTexture = new Texture2D(device, deviceDescription); }
/// <summary> /// Gets a <see cref="Texture" /> output for the specified description. /// </summary> /// <param name="allocator">The allocator.</param> /// <param name="description">The description.</param> /// <returns>A new instance of <see cref="Texture" /> class.</returns> public static Texture GetTemporaryTexture2D(this GraphicsResourceAllocator allocator, TextureDescription description) { return allocator.GetTemporaryTexture(description); }
/// <summary> /// Decodes the TGA file header. /// </summary> /// <param name="stream">The stream.</param> /// <param name="offset">The offset in the stream at which the data starts.</param> /// <param name="convFlags">The conversion flags.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="stream"/> is <see langword="null"/>. /// </exception> /// <exception cref="InvalidDataException"> /// Invalid data. /// </exception> /// <exception cref="NotSupportedException"> /// The specified format is not supported. /// </exception> private static TextureDescription DecodeTGAHeader(Stream stream, out int offset, out ConversionFlags convFlags) { if (stream == null) throw new ArgumentNullException("stream"); TextureDescription description = new TextureDescription { Dimension = TextureDimension.Texture2D, Format = DataFormat.R8G8B8A8_UNORM, }; offset = 0; convFlags = ConversionFlags.None; long size = stream.Length - stream.Position; int sizeOfTGAHeader = Marshal.SizeOf(typeof(Header)); if (size < sizeOfTGAHeader) throw new InvalidDataException("The TGA file is corrupt."); var header = stream.ReadStruct<Header>(); if (header.ColorMapType != 0 || header.ColorMapLength != 0) throw new NotSupportedException("TGA files with color maps are not supported."); if ((header.Descriptor & (DescriptorFlags.Interleaved2Way | DescriptorFlags.Interleaved4Way)) != 0) throw new NotSupportedException("TGA files with interleaved images are not supported."); if (header.Width == 0 || header.Height == 0) throw new NotSupportedException("The TGA file is corrupt. Width and height are invalid."); switch (header.ImageType) { case ImageType.TrueColor: case ImageType.TrueColorRLE: switch (header.BitsPerPixel) { case 16: description.Format = DataFormat.B5G5R5A1_UNORM; break; case 24: description.Format = DataFormat.R8G8B8A8_UNORM; convFlags |= ConversionFlags.Expand; // We could use DXGI_FORMAT_B8G8R8X8_UNORM, but we prefer DXGI 1.0 formats break; case 32: description.Format = DataFormat.R8G8B8A8_UNORM; // We could use DXGI.Format.B8G8R8A8_UNORM, but we prefer DXGI 1.0 formats break; } if (header.ImageType == ImageType.TrueColorRLE) convFlags |= ConversionFlags.RLE; break; case ImageType.BlackAndWhite: case ImageType.BlackAndWhiteRLE: switch (header.BitsPerPixel) { case 8: description.Format = DataFormat.R8_UNORM; break; default: throw new NotSupportedException("The black-and-white format used by the TGA file is not supported. Only 8-bit black-and-white images are supported."); } if (header.ImageType == ImageType.BlackAndWhiteRLE) convFlags |= ConversionFlags.RLE; break; case ImageType.NoImage: case ImageType.ColorMapped: case ImageType.ColorMappedRLE: throw new NotSupportedException("The image format used by the TGA file is not supported."); default: throw new InvalidDataException("Unknown image format used by the TGA file."); } description.Width = header.Width; description.Height = header.Height; description.Depth = 1; description.MipLevels = 1; description.ArraySize = 1; if ((header.Descriptor & DescriptorFlags.InvertX) != 0) convFlags |= ConversionFlags.InvertX; if ((header.Descriptor & DescriptorFlags.InvertY) != 0) convFlags |= ConversionFlags.InvertY; offset = sizeOfTGAHeader; if (header.IDLength != 0) offset += header.IDLength; return description; }
internal TextureCube(GraphicsDevice device, TextureDescription description2D) : base(device, description2D, null) { }
internal TextureCube(GraphicsDevice device, TextureDescription description2D, params DataBox[] dataBoxes) : base(device, description2D, dataBoxes) { }
protected internal Texture1D(GraphicsDevice device, TextureDescription description1D, DataBox[] dataBox = null) : base(device, description1D) { }
private static TextureDescription DecodeMetadata(ImagingFactory imagingFactory, WicFlags flags, BitmapDecoder decoder, BitmapFrameDecode frame, out Guid pixelFormat) { var size = frame.Size; var description = new TextureDescription { Dimension = TextureDimension.Texture2D, Width = size.Width, Height = size.Height, Depth = 1, MipLevels = 1, ArraySize = (flags & WicFlags.AllFrames) != 0 ? decoder.FrameCount : 1, Format = DetermineFormat(imagingFactory, frame.PixelFormat, flags, out pixelFormat) }; if (description.Format == DataFormat.Unknown) throw new NotSupportedException("The pixel format is not supported."); if ((flags & WicFlags.IgnoreSrgb) == 0) { // Handle sRGB. #pragma warning disable 168 try { Guid containerFormat = decoder.ContainerFormat; var metareader = frame.MetadataQueryReader; if (metareader != null) { // Check for sRGB color space metadata. bool sRgb = false; if (containerFormat == ContainerFormatGuids.Png) { // Check for sRGB chunk. if (metareader.GetMetadataByName("/sRGB/RenderingIntent") != null) sRgb = true; } else if (containerFormat == ContainerFormatGuids.Jpeg) { if (Equals(metareader.GetMetadataByName("/app1/ifd/exif/{ushort=40961}"), 1)) sRgb = true; } else if (containerFormat == ContainerFormatGuids.Tiff) { if (Equals(metareader.GetMetadataByName("/ifd/exif/{ushort=40961}"), 1)) sRgb = true; } else { if (Equals(metareader.GetMetadataByName("System.Image.ColorSpace"), 1)) sRgb = true; } if (sRgb) description.Format = TextureHelper.MakeSRgb(description.Format); } } // ReSharper disable once EmptyGeneralCatchClause catch (Exception exception) { // Some formats just don't support metadata (BMP, ICO, etc.). } } #pragma warning restore 168 return description; }
private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var uiProcessor = SceneInstance.GetCurrent(context.RenderContext).GetProcessor <UIRenderProcessor>(); if (uiProcessor == null) { return; } // build the list of the UI elements to render uiElementStates.Clear(); for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderUIElement)renderNode.RenderObject; uiElementStates.Add(new UIElementState(renderElement)); } // evaluate the current draw time (game instance is null for thumbnails) var drawTime = game != null ? game.DrawTime : new GameTime(); // update the rendering context renderingContext.GraphicsContext = context.GraphicsContext; renderingContext.Time = drawTime; renderingContext.RenderTarget = context.CommandList.RenderTargets[0]; // TODO: avoid hardcoded index 0 // Prepare content required for Picking and MouseOver events PickingPrepare(); // allocate temporary graphics resources if needed Texture scopedDepthBuffer = null; foreach (var uiElement in uiElementStates) { if (uiElement.RenderObject.IsFullScreen) { var renderTarget = renderingContext.RenderTarget; var description = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil); scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description); break; } } // see UIElementUnderMouseCursor property UIElement elementUnderMouseCursor = null; // update view parameters and perform UI picking foreach (var uiElementState in uiElementStates) { var renderObject = uiElementState.RenderObject; var rootElement = renderObject.Page?.RootElement; if (rootElement == null) { continue; } UIElement loopedElementUnderMouseCursor = null; // calculate the size of the virtual resolution depending on target size (UI canvas) var virtualResolution = renderObject.Resolution; if (renderObject.IsFullScreen) { //var targetSize = viewportSize; var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height); // update the virtual resolution of the renderer if (renderObject.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight) { virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X; } if (renderObject.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth) { virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y; } uiElementState.Update(renderObject, virtualResolution); } else { var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current); if (cameraComponent != null) { uiElementState.Update(renderObject, cameraComponent); } } // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element) using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate)) { PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime, ref loopedElementUnderMouseCursor); // only update result element, when this one has a value if (loopedElementUnderMouseCursor != null) { elementUnderMouseCursor = loopedElementUnderMouseCursor; } } } UIElementUnderMouseCursor = elementUnderMouseCursor; // render the UI elements of all the entities foreach (var uiElementState in uiElementStates) { var renderObject = uiElementState.RenderObject; var rootElement = renderObject.Page?.RootElement; if (rootElement == null) { continue; } var updatableRootElement = (IUIElementUpdate)rootElement; var virtualResolution = renderObject.Resolution; // update the rendering context values specific to this element renderingContext.Resolution = virtualResolution; renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix; renderingContext.DepthStencilBuffer = renderObject.IsFullScreen ? scopedDepthBuffer : context.CommandList.DepthStencilBuffer; renderingContext.ShouldSnapText = renderObject.SnapText && renderObject.IsBillboard && (renderObject.IsFixedSize || renderObject.IsFullScreen); // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen var virtualOrigin = uiElementState.WorldViewProjectionMatrix.Row4; var virtualWidth = new Vector4(virtualResolution.X / 2, 0, 0, 1); var virtualHeight = new Vector4(0, virtualResolution.Y / 2, 0, 1); var transformedVirtualWidth = Vector4.Zero; var transformedVirtualHeight = Vector4.Zero; for (var i = 0; i < 4; i++) { transformedVirtualWidth[i] = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i]; } var viewportSize = context.CommandList.Viewport.Size; var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W; var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin); var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin); // Set default services rootElement.UIElementServices = new UIElementServices { Services = RenderSystem.Services }; // set default resource dictionary // update layouting context. layoutingContext.VirtualResolution = virtualResolution; layoutingContext.RealResolution = viewportSize; layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y); rootElement.LayoutingContext = layoutingContext; // perform the time-based updates of the UI element updatableRootElement.Update(drawTime); // update the UI element disposition rootElement.Measure(virtualResolution); rootElement.Arrange(virtualResolution, false); // update the UI element hierarchical properties var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is translated by a half resolution compared to its quad, which is centered around the origin updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix); updatableRootElement.UpdateElementState(0); uiElementState.RenderObject.LastRootMatrix = rootMatrix; // clear and set the Depth buffer as required if (renderObject.IsFullScreen) { context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil); } context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget); // start the image draw session renderingContext.StencilTestReferenceValue = 0; batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue); // Render the UI elements in the final render target RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix); // end the image draw session batch.End(); } PickingClear(); // revert the depth stencil buffer to the default value context.CommandList.SetRenderTargets(context.CommandList.DepthStencilBuffer, context.CommandList.RenderTargetCount, context.CommandList.RenderTargets); // Release scroped texture if (scopedDepthBuffer != null) { context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer); } }
protected override Texture CreateTextureCore(ulong nativeTexture, ref TextureDescription description) { ID3D11Texture2D existingTexture = new ID3D11Texture2D((IntPtr)nativeTexture); return(new D3D11Texture(existingTexture, description.Type, description.Format)); }
//-------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="Texture"/> class. /// </summary> /// <param name="description">The description.</param> /// <exception cref="ArgumentException"> /// The <paramref name="description"/> is invalid. /// </exception> public Texture(TextureDescription description) { ValidateTexture(description); Description = description; Images = CreateImageCollection(description); }
internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description) { _gd = gd; _width = description.Width; _height = description.Height; _depth = description.Depth; MipLevels = description.MipLevels; ArrayLayers = description.ArrayLayers; bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap; _actualImageArrayLayers = isCubemap ? 6 * ArrayLayers : ArrayLayers; _format = description.Format; Usage = description.Usage; Type = description.Type; SampleCount = description.SampleCount; VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount); VkFormat = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil); bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging; if (!isStaging) { VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.mipLevels = MipLevels; imageCI.arrayLayers = _actualImageArrayLayers; imageCI.imageType = VkFormats.VdToVkTextureType(Type); imageCI.extent.width = Width; imageCI.extent.height = Height; imageCI.extent.depth = Depth; imageCI.initialLayout = VkImageLayout.Preinitialized; imageCI.usage = VkFormats.VdToVkTextureUsage(Usage); imageCI.tiling = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal; imageCI.format = VkFormat; imageCI.flags = VkImageCreateFlags.MutableFormat; imageCI.samples = VkSampleCount; if (isCubemap) { imageCI.flags |= VkImageCreateFlags.CubeCompatible; } uint subresourceCount = MipLevels * _actualImageArrayLayers * Depth; VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage); CheckResult(result); VkMemoryRequirements memoryRequirements; bool prefersDedicatedAllocation; if (_gd.GetImageMemoryRequirements2 != null) { VkImageMemoryRequirementsInfo2KHR memReqsInfo2 = VkImageMemoryRequirementsInfo2KHR.New(); memReqsInfo2.image = _optimalImage; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetImageMemoryRequirements2(_gd.Device, &memReqsInfo2, &memReqs2); memoryRequirements = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetImageMemoryRequirements(gd.Device, _optimalImage, out memoryRequirements); prefersDedicatedAllocation = false; } VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment, prefersDedicatedAllocation, _optimalImage, Vulkan.VkBuffer.Null); _memoryBlock = memoryToken; result = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); _imageLayouts = new VkImageLayout[subresourceCount]; for (int i = 0; i < _imageLayouts.Length; i++) { _imageLayouts[i] = VkImageLayout.Preinitialized; } } else // isStaging { uint depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(Width, Format), Height, Format); uint stagingSize = depthPitch * Depth; for (uint level = 1; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(mipWidth, Format), mipHeight, Format); stagingSize += depthPitch * mipDepth; } stagingSize *= ArrayLayers; VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.usage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst; bufferCI.size = stagingSize; VkResult result = vkCreateBuffer(_gd.Device, ref bufferCI, null, out _stagingBuffer); CheckResult(result); VkMemoryRequirements bufferMemReqs; bool prefersDedicatedAllocation; if (_gd.GetBufferMemoryRequirements2 != null) { VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New(); memReqInfo2.buffer = _stagingBuffer; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2); bufferMemReqs = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetBufferMemoryRequirements(gd.Device, _stagingBuffer, out bufferMemReqs); prefersDedicatedAllocation = false; } _memoryBlock = _gd.MemoryManager.Allocate( _gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, true, bufferMemReqs.size, bufferMemReqs.alignment, prefersDedicatedAllocation, VkImage.Null, _stagingBuffer); result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); } ClearIfRenderTarget(); TransitionIfSampled(); RefCount = new ResourceRefCount(RefCountedDispose); }
public static unsafe Texture LoadTexture( GraphicsDevice gd, ResourceFactory factory, Stream assetStream, PixelFormat format) { KtxFile ktxTex2D = Load(assetStream, false); uint width = ktxTex2D.Header.PixelWidth; uint height = ktxTex2D.Header.PixelHeight; if (height == 0) { height = width; } uint arrayLayers = Math.Max(1, ktxTex2D.Header.NumberOfArrayElements); uint mipLevels = Math.Max(1, ktxTex2D.Header.NumberOfMipmapLevels); Texture ret = factory.CreateTexture(TextureDescription.Texture2D( width, height, mipLevels, arrayLayers, format, TextureUsage.Sampled)); Texture stagingTex = factory.CreateTexture(TextureDescription.Texture2D( width, height, mipLevels, arrayLayers, format, TextureUsage.Staging)); // Copy texture data into staging buffer for (uint level = 0; level < mipLevels; level++) { KtxMipmapLevel mipmap = ktxTex2D.Mipmaps[level]; for (uint layer = 0; layer < arrayLayers; layer++) { KtxArrayElement ktxLayer = mipmap.ArrayElements[layer]; Debug.Assert(ktxLayer.Faces.Length == 1); byte[] pixelData = ktxLayer.Faces[0].Data; fixed(byte *pixelDataPtr = &pixelData[0]) { gd.UpdateTexture(stagingTex, (IntPtr)pixelDataPtr, (uint)pixelData.Length, 0, 0, 0, mipmap.Width, mipmap.Height, 1, level, layer); } } } CommandList copyCL = factory.CreateCommandList(); copyCL.Begin(); for (uint level = 0; level < mipLevels; level++) { KtxMipmapLevel mipLevel = ktxTex2D.Mipmaps[level]; for (uint layer = 0; layer < arrayLayers; layer++) { copyCL.CopyTexture( stagingTex, 0, 0, 0, level, layer, ret, 0, 0, 0, level, layer, mipLevel.Width, mipLevel.Height, mipLevel.Depth, 1); } } copyCL.End(); gd.SubmitCommands(copyCL); gd.DisposeWhenIdle(copyCL); gd.DisposeWhenIdle(stagingTex); return(ret); }
private static TextureDescription DecodeDDSHeader(BinaryReader reader, DdsFlags flags, out ConversionFlags convFlags) { Debug.Assert(Marshal.SizeOf(typeof(Header)) == 124, "DDS Header size mismatch"); Debug.Assert(Marshal.SizeOf(typeof(HeaderDXT10)) == 20, "DDS DX10 Extended Header size mismatch"); var description = new TextureDescription(); convFlags = ConversionFlags.None; long size = reader.BaseStream.Length - reader.BaseStream.Position; int sizeOfTGAHeader = Marshal.SizeOf(typeof(Header)); if (size < sizeOfTGAHeader) throw new InvalidDataException("The DDS file is corrupt."); // DDS files always start with the same magic number ("DDS "). if (reader.ReadUInt32() != MagicHeader) throw new InvalidDataException("The file does not appear to be a DDS file."); var header = reader.BaseStream.ReadStruct<Header>(); // Verify header to validate DDS file if (header.Size != Marshal.SizeOf(typeof(Header)) || header.PixelFormat.Size != Marshal.SizeOf(typeof(PixelFormat))) throw new InvalidDataException("Incorrect sizes in DDS file."); description.MipLevels = header.MipMapCount; if (description.MipLevels == 0) description.MipLevels = 1; // Check for DX10 extension if ((header.PixelFormat.Flags & PixelFormatFlags.FourCC) != 0 && (new FourCC('D', 'X', '1', '0') == header.PixelFormat.FourCC)) { // Buffer must be big enough for both headers and magic value if (reader.BaseStream.Length < (Marshal.SizeOf(typeof(Header)) + Marshal.SizeOf(typeof(HeaderDXT10)) + sizeof(uint))) throw new InvalidDataException("The DDS files is truncated."); var headerDX10 = reader.BaseStream.ReadStruct<HeaderDXT10>(); convFlags |= ConversionFlags.DX10; description.ArraySize = headerDX10.ArraySize; if (description.ArraySize == 0) throw new InvalidDataException("Invalid array size specified in DDS file."); description.Format = headerDX10.DXGIFormat; if (!TextureHelper.IsValidDds(description.Format) || TextureHelper.IsPalettized(description.Format)) throw new InvalidDataException("Invalid format specified in DDS file."); switch (headerDX10.ResourceDimension) { case ResourceDimension.Texture1D: // D3DX writes 1D textures with a fixed Height of 1 if ((header.Flags & HeaderFlags.Height) != 0 && header.Height != 1) throw new InvalidDataException("Invalid height for 1D texture specified in DDS file."); description.Dimension = TextureDimension.Texture1D; description.Width = header.Width; description.Height = 1; description.Depth = 1; break; case ResourceDimension.Texture2D: if ((headerDX10.MiscFlags & ResourceOptionFlags.TextureCube) != 0) { description.Dimension = TextureDimension.TextureCube; description.ArraySize *= 6; } else { description.Dimension = TextureDimension.Texture2D; } description.Width = header.Width; description.Height = header.Height; description.Depth = 1; break; case ResourceDimension.Texture3D: if ((header.Flags & HeaderFlags.Volume) == 0) throw new InvalidDataException("Volume flag for 3D texture is missing in DDS file."); if (description.ArraySize > 1) throw new InvalidDataException("Invalid array size for 3D texture specified in DDS file."); description.Dimension = TextureDimension.Texture3D; description.Width = header.Width; description.Height = header.Height; description.Depth = header.Depth; break; default: throw new InvalidDataException(string.Format(CultureInfo.InvariantCulture, "Invalid texture dimension specified in DDS file.")); } } else { description.ArraySize = 1; if ((header.Flags & HeaderFlags.Volume) != 0) { description.Dimension = TextureDimension.Texture3D; description.Width = header.Width; description.Height = header.Height; description.Depth = header.Depth; } else { if ((header.CubemapFlags & CubemapFlags.CubeMap) != 0) { // We require all six faces to be defined if ((header.CubemapFlags & CubemapFlags.AllFaces) != CubemapFlags.AllFaces) throw new InvalidDataException("Cube map faces missing in DDS file. All six faces required."); description.Dimension = TextureDimension.TextureCube; description.ArraySize = 6; } else { description.Dimension = TextureDimension.Texture2D; } description.Width = header.Width; description.Height = header.Height; description.Depth = 1; // Note there's no way for a legacy Direct3D 9 DDS to express a '1D' texture } description.Format = GetDXGIFormat(ref header.PixelFormat, flags, out convFlags); if (description.Format == DataFormat.Unknown) throw new NotSupportedException("The texture format used in the DDS file is not supported."); // Premultiplied formats are considered deprecated. //if ((convFlags & ConversionFlags.PremultipliedAlpha) != 0) // Description.AlphaMode = AlphaMode.Premultiplied; // Special flag for handling LUMINANCE legacy formats if ((flags & DdsFlags.ExpandLuminance) != 0) { switch (description.Format) { case DataFormat.R8_UNORM: description.Format = DataFormat.R8G8B8A8_UNORM; convFlags |= ConversionFlags.FormatL8 | ConversionFlags.Expand; break; case DataFormat.R8G8_UNORM: description.Format = DataFormat.R8G8B8A8_UNORM; convFlags |= ConversionFlags.FormatA8L8 | ConversionFlags.Expand; break; case DataFormat.R16_UNORM: description.Format = DataFormat.R16G16B16A16_UNORM; convFlags |= ConversionFlags.FormatL16 | ConversionFlags.Expand; break; } } } // Special flag for handling BGR DXGI 1.1 formats if ((flags & DdsFlags.ForceRgb) != 0) { switch (description.Format) { case DataFormat.B8G8R8A8_UNORM: description.Format = DataFormat.R8G8B8A8_UNORM; convFlags |= ConversionFlags.Swizzle; break; case DataFormat.B8G8R8X8_UNORM: description.Format = DataFormat.R8G8B8A8_UNORM; convFlags |= ConversionFlags.Swizzle | ConversionFlags.NoAlpha; break; case DataFormat.B8G8R8A8_TYPELESS: description.Format = DataFormat.R8G8B8A8_TYPELESS; convFlags |= ConversionFlags.Swizzle; break; case DataFormat.B8G8R8A8_UNORM_SRGB: description.Format = DataFormat.R8G8B8A8_UNORM_SRGB; convFlags |= ConversionFlags.Swizzle; break; case DataFormat.B8G8R8X8_TYPELESS: description.Format = DataFormat.R8G8B8A8_TYPELESS; convFlags |= ConversionFlags.Swizzle | ConversionFlags.NoAlpha; break; case DataFormat.B8G8R8X8_UNORM_SRGB: description.Format = DataFormat.R8G8B8A8_UNORM_SRGB; convFlags |= ConversionFlags.Swizzle | ConversionFlags.NoAlpha; break; } } // Special flag for handling 16bpp formats if ((flags & DdsFlags.No16Bpp) != 0) { switch (description.Format) { case DataFormat.B5G6R5_UNORM: case DataFormat.B5G5R5A1_UNORM: case DataFormat.B4G4R4A4_UNORM: description.Format = DataFormat.R8G8B8A8_UNORM; convFlags |= ConversionFlags.Expand; if (description.Format == DataFormat.B5G6R5_UNORM) convFlags |= ConversionFlags.NoAlpha; break; } } return description; }
public unsafe void Copy_Compressed_Array(bool separateLayerCopies) { PixelFormat format = PixelFormat.BC3_UNorm; if (!GD.GetPixelFormatSupport(format, TextureType.Texture2D, TextureUsage.Sampled)) { return; } TextureDescription texDesc = TextureDescription.Texture2D( 16, 16, 1, 4, format, TextureUsage.Sampled); Texture copySrc = RF.CreateTexture(texDesc); texDesc.Usage = TextureUsage.Staging; Texture copyDst = RF.CreateTexture(texDesc); for (uint layer = 0; layer < copySrc.ArrayLayers; layer++) { int byteCount = 16 * 16; byte[] data = Enumerable.Range(0, byteCount).Select(i => (byte)(i + layer)).ToArray(); GD.UpdateTexture( copySrc, data, 0, 0, 0, 16, 16, 1, 0, layer); } CommandList copyCL = RF.CreateCommandList(); copyCL.Begin(); if (separateLayerCopies) { for (uint layer = 0; layer < copySrc.ArrayLayers; layer++) { copyCL.CopyTexture(copySrc, 0, 0, 0, 0, layer, copyDst, 0, 0, 0, 0, layer, 16, 16, 1, 1); } } else { copyCL.CopyTexture(copySrc, 0, 0, 0, 0, 0, copyDst, 0, 0, 0, 0, 0, 16, 16, 1, copySrc.ArrayLayers); } copyCL.End(); Fence fence = RF.CreateFence(false); GD.SubmitCommands(copyCL, fence); GD.WaitForFence(fence); for (uint layer = 0; layer < copyDst.ArrayLayers; layer++) { MappedResource map = GD.Map(copyDst, MapMode.Read, layer); byte * basePtr = (byte *)map.Data; int index = 0; uint rowSize = 64; uint numRows = 4; for (uint row = 0; row < numRows; row++) { byte *rowBase = basePtr + (row * map.RowPitch); for (uint x = 0; x < rowSize; x++) { Assert.Equal((byte)(index + layer), rowBase[x]); index += 1; } } GD.Unmap(copyDst, layer); } }
private static Texture DecodeSingleframe(ImagingFactory imagingFactory, WicFlags flags, TextureDescription description, Guid convertGuid, BitmapFrameDecode frame) { var texture = new Texture(description); var image = texture.Images[0]; if (convertGuid == Guid.Empty) { frame.CopyPixels(image.Data, image.RowPitch); } else { using (var converter = new FormatConverter(imagingFactory)) { converter.Initialize(frame, convertGuid, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); converter.CopyPixels(image.Data, image.RowPitch); } } return texture; }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { base.Draw(context, renderView, renderViewStage, startIndex, endIndex); var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current); var uiProcessor = renderView.SceneInstance.GetProcessor <UIRenderProcessor>(); if (uiProcessor == null) { return; } //foreach (var uiRoot in uiProcessor.UIRoots) //{ // // Perform culling on group and accept // if (!renderView.SceneCameraRenderer.CullingMask.Contains(uiRoot.UIComponent.Entity.Group)) // continue; // // skips empty UI elements // if (uiRoot.UIComponent.RootElement == null) // continue; // // Project the position // // TODO: This code is duplicated from SpriteComponent -> unify it at higher level? // var worldPosition = new Vector4(uiRoot.TransformComponent.WorldMatrix.TranslationVector, 1.0f); // float projectedZ; // if (uiRoot.UIComponent.IsFullScreen) // { // projectedZ = -uiRoot.TransformComponent.WorldMatrix.M43; // } // else // { // Vector4 projectedPosition; // var cameraComponent = renderView.Camera; // if (cameraComponent == null) // continue; // Vector4.Transform(ref worldPosition, ref cameraComponent.ViewProjectionMatrix, out projectedPosition); // projectedZ = projectedPosition.Z / projectedPosition.W; // } // transparentList.Add(new RenderItem(this, uiRoot, projectedZ)); //} // build the list of the UI elements to render uiElementStates.Clear(); for (var index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderElement = (RenderUIElement)renderNode.RenderObject; uiElementStates.Add(renderElement); } // evaluate the current draw time (game instance is null for thumbnails) var drawTime = game != null ? game.DrawTime : new GameTime(); // update the rendering context renderingContext.GraphicsContext = context.GraphicsContext; renderingContext.Time = drawTime; renderingContext.RenderTarget = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0 // cache the ratio between viewport and target. var viewportSize = context.CommandList.Viewport.Size; viewportTargetRatio = new Vector2(viewportSize.X / renderingContext.RenderTarget.Width, viewportSize.Y / renderingContext.RenderTarget.Height); // compact all the pointer events that happened since last frame to avoid performing useless hit tests. CompactPointerEvents(); // allocate temporary graphics resources if needed Texture scopedDepthBuffer = null; foreach (var uiElement in uiElementStates) { if (uiElement.UIComponent.IsFullScreen) { var renderTarget = renderingContext.RenderTarget; var description = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil); scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description); break; } } // render the UI elements of all the entities foreach (var uiElementState in uiElementStates) { var uiComponent = uiElementState.UIComponent; var rootElement = uiComponent.RootElement; if (rootElement == null) { continue; } var updatableRootElement = (IUIElementUpdate)rootElement; // calculate the size of the virtual resolution depending on target size (UI canvas) var virtualResolution = uiComponent.VirtualResolution; var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height); if (uiComponent.IsFullScreen) { // update the virtual resolution of the renderer if (uiComponent.VirtualResolutionMode == VirtualResolutionMode.FixedWidthAdaptableHeight) { virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X; } if (uiComponent.VirtualResolutionMode == VirtualResolutionMode.FixedHeightAdaptableWidth) { virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y; } } // Update the view parameters if (uiComponent.IsFullScreen) { viewParameters.Update(uiComponent.Entity, virtualResolution); } else { var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current); viewParameters.Update(uiComponent.Entity, cameraComponent); } // Analyze the input and trigger the UI element touch and key events // Note: this is done before measuring/arranging/drawing the element in order to avoid one frame latency on clicks. // But by doing so the world matrices taken for hit test are the ones calculated during last frame. using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate)) { foreach (var uiState in uiElementStates) { if (uiState.UIComponent.RootElement == null) { continue; } UpdateMouseOver(uiState); UpdateTouchEvents(uiState, drawTime); } } // update the rendering context values specific to this element renderingContext.Resolution = virtualResolution; renderingContext.ViewMatrix = viewParameters.ViewMatrix; renderingContext.ProjectionMatrix = viewParameters.ProjectionMatrix; renderingContext.ViewProjectionMatrix = viewParameters.ViewProjectionMatrix; renderingContext.DepthStencilBuffer = uiComponent.IsFullScreen ? scopedDepthBuffer : currentRenderFrame.DepthStencil; renderingContext.ShouldSnapText = uiComponent.SnapText; // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen var virtualOrigin = viewParameters.ViewProjectionMatrix.Row4; var virtualWidth = new Vector4(virtualResolution.X / 2, 0, 0, 1); var virtualHeight = new Vector4(0, virtualResolution.Y / 2, 0, 1); var transformedVirtualWidth = Vector4.Zero; var transformedVirtualHeight = Vector4.Zero; for (int i = 0; i < 4; i++) { transformedVirtualWidth[i] = virtualWidth[0] * viewParameters.ViewProjectionMatrix[0 + i] + viewParameters.ViewProjectionMatrix[12 + i]; transformedVirtualHeight[i] = virtualHeight[1] * viewParameters.ViewProjectionMatrix[4 + i] + viewParameters.ViewProjectionMatrix[12 + i]; } var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W; var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin); var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin); // set default resource dictionary rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary; // update layouting context. layoutingContext.VirtualResolution = virtualResolution; layoutingContext.RealResolution = viewportSize; layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y); rootElement.LayoutingContext = layoutingContext; // perform the time-based updates of the UI element updatableRootElement.Update(drawTime); // update the UI element disposition rootElement.Measure(virtualResolution); rootElement.Arrange(virtualResolution, false); // update the UI element hierarchical properties var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is rotated of 180degrees along Ox updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.LastRootMatrix); updatableRootElement.UpdateElementState(0); uiElementState.LastRootMatrix = rootMatrix; // clear and set the Depth buffer as required if (uiComponent.IsFullScreen) { context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil); } context.CommandList.SetRenderTargetAndViewport(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget); // start the image draw session renderingContext.StencilTestReferenceValue = 0; batch.Begin(context.GraphicsContext, ref viewParameters.ViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue); // Render the UI elements in the final render target ReccursiveDrawWithClipping(context, rootElement); // end the image draw session batch.End(); } // clear the list of compacted pointer events of time frame ClearPointerEvents(); // revert the depth stencil buffer to the default value context.CommandList.SetRenderTargetsAndViewport(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets); // Release scroped texture if (scopedDepthBuffer != null) { context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer); } }
private unsafe Texture CreateTexture(TextKey key) { var size = key.Size; var actualFont = key.Font; var image = _textImagePool.Acquire(new ImageKey { Width = (int)Math.Ceiling(size.Width), Height = (int)Math.Ceiling(size.Height) }); // Clear image to transparent. // TODO: Don't need to do this for a newly created image. fixed(void *pin = &image.DangerousGetPinnableReferenceToPixelBuffer()) { Unsafe.InitBlock(pin, 0, (uint)(image.Width * image.Height * 4)); } image.Mutate(x => { var location = new SixLabors.Primitives.PointF(0, size.Height / 2.0f); // TODO: Vertical centering is not working properly. location.Y *= 0.8f; var color = key.Color; x.DrawText( key.Text, actualFont, new Bgra32( (byte)(color.R * 255.0f), (byte)(color.G * 255.0f), (byte)(color.B * 255.0f), (byte)(color.A * 255.0f)), location, new TextGraphicsOptions { WrapTextWidth = size.Width, HorizontalAlignment = key.Alignment == TextAlignment.Center ? HorizontalAlignment.Center : HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }); }); Texture texture; // Draw image to texture. fixed(void *pin = &image.DangerousGetPinnableReferenceToPixelBuffer()) { texture = _graphicsDevice.ResourceFactory.CreateTexture( TextureDescription.Texture2D( (uint)image.Width, (uint)image.Height, 1, 1, PixelFormat.B8_G8_R8_A8_UNorm, TextureUsage.Sampled)); _graphicsDevice.UpdateTexture( texture, new IntPtr(pin), (uint)(image.Width * image.Height * 4), 0, 0, 0, texture.Width, texture.Height, 1, 0, 0); } _textImagePool.ReleaseAll(); return(texture); }
public abstract Texture CreateTexture(ref TextureDescription description);
// TODO: private protected /// <summary> /// </summary> /// <param name="description"></param> /// <returns></returns> protected abstract Texture CreateTextureCore(ref TextureDescription description);
protected override void DrawCore(RenderContext context, RenderDrawContext drawContext) { var viewport = drawContext.CommandList.Viewport; using (drawContext.PushRenderTargetsAndRestore()) { // Render Shadow maps shadowMapRenderer?.Draw(drawContext); if (VRSettings.Enabled && VRSettings.VRDevice != null) { var isFullViewport = (int)viewport.X == 0 && (int)viewport.Y == 0 && (int)viewport.Width == drawContext.CommandList.RenderTarget.ViewWidth && (int)viewport.Height == drawContext.CommandList.RenderTarget.ViewHeight; if (!isFullViewport) { return; } var hasPostEffects = PostEffects != null; // When we have post effect we need to bind a different framebuffer for each view to be sure effects impinge on the other view. Texture vrFullSurface; using (drawContext.PushRenderTargetsAndRestore()) { var currentRenderTarget = drawContext.CommandList.RenderTarget; var vrFullFrameSize = VRSettings.VRDevice.ActualRenderFrameSize; var desiredRenderTargetSize = !hasPostEffects ? vrFullFrameSize : new Size2(vrFullFrameSize.Width / 2, vrFullFrameSize.Height); if (hasPostEffects || desiredRenderTargetSize.Width != currentRenderTarget.Width || desiredRenderTargetSize.Height != currentRenderTarget.Height) { drawContext.CommandList.SetRenderTargets(null, null); // force to create and bind a new render target } PrepareRenderTargets(drawContext, desiredRenderTargetSize); //prepare the final VR target vrFullSurface = ViewOutputTarget; if (hasPostEffects) { var frameSize = VRSettings.VRDevice.ActualRenderFrameSize; var renderTargetDescription = TextureDescription.New2D(frameSize.Width, frameSize.Height, 1, PixelFormat.R8G8B8A8_UNorm_SRgb, TextureFlags.ShaderResource | TextureFlags.RenderTarget); vrFullSurface = PushScopedResource(drawContext.GraphicsContext.Allocator.GetTemporaryTexture2D(renderTargetDescription)); } //draw per eye using (context.SaveViewportAndRestore()) using (drawContext.PushRenderTargetsAndRestore()) { ViewCount = 2; bool isWindowsMixedReality = false; for (var i = 0; i < 2; i++) { #if XENKO_GRAPHICS_API_DIRECT3D11 && XENKO_PLATFORM_UWP if (drawContext.GraphicsDevice.Presenter is WindowsMixedRealityGraphicsPresenter graphicsPresenter) { isWindowsMixedReality = true; MSAALevel = MultisampleCount.None; currentRenderTargets.Clear(); if (i == 0) { currentRenderTargets.Add(graphicsPresenter.LeftEyeBuffer); } else { currentRenderTargets.Add(graphicsPresenter.RightEyeBuffer); } } #endif drawContext.CommandList.SetRenderTargets(currentDepthStencil, currentRenderTargets.Count, currentRenderTargets.Items); if (!hasPostEffects && !isWindowsMixedReality) // need to change the viewport between each eye { var frameSize = VRSettings.VRDevice.ActualRenderFrameSize; drawContext.CommandList.SetViewport(new Viewport(i * frameSize.Width / 2, 0, frameSize.Width / 2, frameSize.Height)); } else if (i == 0) // the viewport is the same for both eyes so we set it only once { drawContext.CommandList.SetViewport(new Viewport(0.0f, 0.0f, VRSettings.VRDevice.ActualRenderFrameSize.Width / 2.0f, VRSettings.VRDevice.ActualRenderFrameSize.Height)); } using (context.PushRenderViewAndRestore(VRSettings.RenderViews[i])) { // Clear render target and depth stencil if (hasPostEffects || i == 0) // need to clear for each eye in the case we have two different render targets { Clear?.Draw(drawContext); } ViewIndex = i; DrawView(context, drawContext, i, 2); if (hasPostEffects) // copy the rendered view into the vr full view framebuffer { drawContext.CommandList.CopyRegion(ViewOutputTarget, 0, null, vrFullSurface, 0, VRSettings.VRDevice.ActualRenderFrameSize.Width / 2 * i); } } } if (VRSettings.VRDevice.SupportsOverlays) { foreach (var overlay in VRSettings.Overlays) { if (overlay != null && overlay.Texture != null) { overlay.Overlay.UpdateSurface(drawContext.CommandList, overlay.Texture); } } } VRSettings.VRDevice.Commit(drawContext.CommandList, vrFullSurface); } } //draw mirror to backbuffer (if size is matching and full viewport) if (VRSettings.CopyMirror) { CopyOrScaleTexture(drawContext, VRSettings.VRDevice.MirrorTexture, drawContext.CommandList.RenderTarget); } else if (hasPostEffects) { CopyOrScaleTexture(drawContext, vrFullSurface, drawContext.CommandList.RenderTarget); } } else { PrepareRenderTargets(drawContext, new Size2((int)viewport.Width, (int)viewport.Height)); ViewCount = 1; ViewIndex = 0; //var sssMaterialIndexRenderTarget = GenerateSSSMaterialIndexRenderTarget(context, viewport); using (drawContext.PushRenderTargetsAndRestore()) { drawContext.CommandList.SetRenderTargets(currentDepthStencil, currentRenderTargets.Count, currentRenderTargets.Items); // Clear render target and depth stencil Clear?.Draw(drawContext); DrawView(context, drawContext, 0, 1); } } } // Clear intermediate results currentRenderTargets.Clear(); currentRenderTargetsNonMSAA.Clear(); currentDepthStencil = null; currentDepthStencilNonMSAA = null; }
public StandardGraphicsResources(GraphicsDevice graphicsDevice) { _graphicsDevice = graphicsDevice; var linearClampSamplerDescription = SamplerDescription.Linear; linearClampSamplerDescription.AddressModeU = SamplerAddressMode.Clamp; linearClampSamplerDescription.AddressModeV = SamplerAddressMode.Clamp; linearClampSamplerDescription.AddressModeW = SamplerAddressMode.Clamp; LinearClampSampler = AddDisposable( graphicsDevice.ResourceFactory.CreateSampler(ref linearClampSamplerDescription)); var pointClampSamplerDescription = SamplerDescription.Point; pointClampSamplerDescription.AddressModeU = SamplerAddressMode.Clamp; pointClampSamplerDescription.AddressModeV = SamplerAddressMode.Clamp; pointClampSamplerDescription.AddressModeW = SamplerAddressMode.Clamp; PointClampSampler = AddDisposable( graphicsDevice.ResourceFactory.CreateSampler(ref pointClampSamplerDescription)); NullTexture = AddDisposable(graphicsDevice.ResourceFactory.CreateTexture(TextureDescription.Texture2D(1, 1, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled))); NullTexture.Name = "Null Texture"; SolidWhiteTexture = AddDisposable(graphicsDevice.CreateStaticTexture2D( 1, 1, 1, new TextureMipMapData( new byte[] { 255, 255, 255, 255 }, 4, 4, 1, 1), PixelFormat.R8_G8_B8_A8_UNorm)); SolidWhiteTexture.Name = "Solid White Texture"; PlaceholderTexture = AddDisposable(graphicsDevice.CreateStaticTexture2D( 1, 1, 1, new TextureMipMapData( new byte[] { 255, 105, 180, 255 }, 4, 4, 1, 1), PixelFormat.R8_G8_B8_A8_UNorm)); PlaceholderTexture.Name = "Placeholder Texture"; _nullStructuredBuffers = new Dictionary <uint, DeviceBuffer>(); }
public void Parse(byte[] byteCode, ShaderStage stage) { ConstantBufferMappings.Clear(); TextureMappings.Clear(); UAVMappings.Clear(); SamplerMappings.Clear(); using (var reflection = new ShaderReflection(byteCode)) { FeatureLevel = reflection.MinFeatureLevel; for (int i = 0; i < reflection.Description.BoundResources; ++i) { var res = reflection.GetResourceBindingDescription(i); switch (res.Type) { case ShaderInputType.ConstantBuffer: var cb = reflection.GetConstantBuffer(res.Name); var cbDesc = new ConstantBufferDescription(res.Name, cb.Description.Size) { Stage = stage }; ConstantBufferMappings.Add(res.Name, cbDesc.CreateMapping(res.BindPoint)); break; case ShaderInputType.Texture: var tDescT = new TextureDescription(res.Name, stage, TextureType.Texture); TextureMappings.Add(res.Name, tDescT.CreateMapping(res.BindPoint)); break; case ShaderInputType.Structured: var tDescStr = new TextureDescription(res.Name, stage, TextureType.Structured); TextureMappings.Add(res.Name, tDescStr.CreateMapping(res.BindPoint)); break; case ShaderInputType.TextureBuffer: var tDescTB = new TextureDescription(res.Name, stage, TextureType.TextureBuffer); TextureMappings.Add(res.Name, tDescTB.CreateMapping(res.BindPoint)); break; case ShaderInputType.UnorderedAccessViewAppendStructured: var uDescAppend = new UAVDescription(res.Name, stage, UnorderedAccessViewType.AppendStructured); UAVMappings.Add(res.Name, uDescAppend.CreateMapping(res.BindPoint)); break; case ShaderInputType.UnorderedAccessViewConsumeStructured: var uDescConsume = new UAVDescription(res.Name, stage, UnorderedAccessViewType.ConsumeStructured); UAVMappings.Add(res.Name, uDescConsume.CreateMapping(res.BindPoint)); break; case ShaderInputType.UnorderedAccessViewRWByteAddress: var uDescByte = new UAVDescription(res.Name, stage, UnorderedAccessViewType.RWByteAddress); UAVMappings.Add(res.Name, uDescByte.CreateMapping(res.BindPoint)); break; case ShaderInputType.UnorderedAccessViewRWStructuredWithCounter: var uDescStr = new UAVDescription(res.Name, stage, UnorderedAccessViewType.RWStructuredWithCounter); UAVMappings.Add(res.Name, uDescStr.CreateMapping(res.BindPoint)); break; case ShaderInputType.UnorderedAccessViewRWTyped: var uDescTyped = new UAVDescription(res.Name, stage, UnorderedAccessViewType.RWTyped); UAVMappings.Add(res.Name, uDescTyped.CreateMapping(res.BindPoint)); break; case ShaderInputType.Sampler: SamplerMappings.Add(res.Name, new SamplerMapping(res.BindPoint, res.Name, stage)); break; } } } }
private void Initialize() { var factory = graphicsDevice.ResourceFactory; aspectWidth = 2f / graphicsDevice.SwapchainFramebuffer.Width; aspectHeight = 2f / graphicsDevice.SwapchainFramebuffer.Height; glyphVertexBuffer = factory.CreateBuffer(new BufferDescription(VertexPosition3Coord2.SizeInBytes, BufferUsage.VertexBuffer)); quadVertexBuffer = factory.CreateBuffer(new BufferDescription(VertexPosition2.SizeInBytes * 4, BufferUsage.VertexBuffer)); quadVertices = new VertexPosition2[] { new VertexPosition2(new Vector2(-1, 1)), new VertexPosition2(new Vector2(-1, -1)), new VertexPosition2(new Vector2(1, 1)), new VertexPosition2(new Vector2(1, -1)), }; graphicsDevice.UpdateBuffer(quadVertexBuffer, 0, quadVertices); textVertexPropertiesBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <TextVertexProperties>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); textFragmentPropertiesBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <TextFragmentProperties>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); textVertexProperties = new TextVertexProperties { Transform = new Matrix4x4(), Rectangle = new Vector4(0, 0, 1, 1) }; textFragmentProperties = new TextFragmentProperties { ThicknessAndMode = 0, // TODO support other modes GlyphColor = new Color(0, 0.5f, 1, 1) }; graphicsDevice.UpdateBuffer(textVertexPropertiesBuffer, 0, textVertexProperties); graphicsDevice.UpdateBuffer(textFragmentPropertiesBuffer, 0, textFragmentProperties); var colorFormat = PixelFormat.B8_G8_R8_A8_UNorm; glyphTexture = factory.CreateTexture(TextureDescription.Texture2D(graphicsDevice.SwapchainFramebuffer.Width, graphicsDevice.SwapchainFramebuffer.Height, 1, 1, colorFormat, TextureUsage.RenderTarget | TextureUsage.Sampled)); glyphTextureView = factory.CreateTextureView(glyphTexture); glyphTextureFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(null, glyphTexture)); // HACK workaround issue with texture view caching for shader resources dummyTexture = factory.CreateTexture(TextureDescription.Texture2D(1, 1, 1, 1, colorFormat, TextureUsage.Sampled)); dummyTextureView = factory.CreateTextureView(dummyTexture); var shaderOptions = GetCompileOptions(); CompileShaders(factory, shaderOptions); var textPropertiesLayout = factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("TextVertexPropertiesBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("TextFragmentPropertiesBuffer", ResourceKind.UniformBuffer, ShaderStages.Fragment))); textTextureLayout = factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("GlyphTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("GlyphTextureSampler", ResourceKind.Sampler, ShaderStages.Fragment))); textPropertiesSet = factory.CreateResourceSet(new ResourceSetDescription( textPropertiesLayout, textVertexPropertiesBuffer, textFragmentPropertiesBuffer)); textTextureSet = factory.CreateResourceSet(new ResourceSetDescription( textTextureLayout, glyphTextureView, graphicsDevice.LinearSampler)); // HACK workaround issue with texture view caching for shader resources dummyTextureSet = factory.CreateResourceSet(new ResourceSetDescription( textTextureLayout, dummyTextureView, graphicsDevice.LinearSampler)); var additiveBlendState = new BlendStateDescription(RgbaFloat.White, new BlendAttachmentDescription( blendEnabled: true, sourceColorFactor: BlendFactor.One, destinationColorFactor: BlendFactor.One, colorFunction: BlendFunction.Add, sourceAlphaFactor: BlendFactor.One, destinationAlphaFactor: BlendFactor.One, alphaFunction: BlendFunction.Add)); var pipelineDescription = new GraphicsPipelineDescription( blendState: new BlendStateDescription(RgbaFloat.White, new BlendAttachmentDescription( blendEnabled: true, sourceColorFactor: BlendFactor.Zero, destinationColorFactor: BlendFactor.SourceColor, colorFunction: BlendFunction.Add, sourceAlphaFactor: BlendFactor.Zero, destinationAlphaFactor: BlendFactor.SourceAlpha, alphaFunction: BlendFunction.Add)), depthStencilStateDescription: new DepthStencilStateDescription( depthTestEnabled: true, depthWriteEnabled: true, comparisonKind: ComparisonKind.LessEqual), rasterizerState: new RasterizerStateDescription( cullMode: FaceCullMode.Back, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false), primitiveTopology: PrimitiveTopology.TriangleStrip, shaderSet: new ShaderSetDescription( vertexLayouts: new[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)) }, shaders: textShaders, specializations: shaderOptions.Specializations), resourceLayouts: new ResourceLayout[] { textPropertiesLayout, textTextureLayout }, outputs: graphicsDevice.SwapchainFramebuffer.OutputDescription ); outputPipeline = factory.CreateGraphicsPipeline(pipelineDescription); pipelineDescription.BlendState = additiveBlendState; outputColorPipeline = factory.CreateGraphicsPipeline(pipelineDescription); pipelineDescription.Outputs = new OutputDescription(null, new OutputAttachmentDescription(colorFormat)); pipelineDescription.BlendState = additiveBlendState; pipelineDescription.ResourceLayouts = new ResourceLayout[] { textPropertiesLayout }; pipelineDescription.PrimitiveTopology = PrimitiveTopology.TriangleList; pipelineDescription.RasterizerState = new RasterizerStateDescription( cullMode: FaceCullMode.None, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false); pipelineDescription.ShaderSet = new ShaderSetDescription( vertexLayouts: new[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3), new VertexElementDescription("Coord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)) }, shaders: glyphShaders, specializations: shaderOptions.Specializations); glyphPipeline = factory.CreateGraphicsPipeline(pipelineDescription); }
public void Points_WithUShortColor() { Texture target = RF.CreateTexture(TextureDescription.Texture2D( 50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget)); Texture staging = RF.CreateTexture(TextureDescription.Texture2D( 50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging)); Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, target)); DeviceBuffer infoBuffer = RF.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer)); DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); Matrix4x4 orthoMatrix = Matrix4x4.CreateOrthographicOffCenter( 0, framebuffer.Width, framebuffer.Height, 0, -1, 1); GD.UpdateBuffer(orthoBuffer, 0, ref orthoMatrix); ShaderSetDescription shaderSet = new ShaderSetDescription( new VertexLayoutDescription[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2), new VertexElementDescription("Color_UInt", VertexElementSemantic.Color, VertexElementFormat.UShort4)) }, new Shader[] { TestShaders.Load(RF, "U16VertexAttribs", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "U16VertexAttribs", ShaderStages.Fragment, "FS") }); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex))); ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, infoBuffer, orthoBuffer)); GraphicsPipelineDescription gpd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.PointList, shaderSet, layout, framebuffer.OutputDescription); Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd); uint colorNormalizationFactor = 2500; VertexCPU_UShort[] vertices = new VertexCPU_UShort[] { new VertexCPU_UShort { Position = new Vector2(0.5f, 0.5f), R = (ushort)(0.25f * colorNormalizationFactor), G = (ushort)(0.5f * colorNormalizationFactor), B = (ushort)(0.75f * colorNormalizationFactor), }, new VertexCPU_UShort { Position = new Vector2(10.5f, 12.5f), R = (ushort)(0.25f * colorNormalizationFactor), G = (ushort)(0.5f * colorNormalizationFactor), B = (ushort)(0.75f * colorNormalizationFactor), }, new VertexCPU_UShort { Position = new Vector2(25.5f, 35.5f), R = (ushort)(0.75f * colorNormalizationFactor), G = (ushort)(0.5f * colorNormalizationFactor), B = (ushort)(0.25f * colorNormalizationFactor), }, new VertexCPU_UShort { Position = new Vector2(49.5f, 49.5f), R = (ushort)(0.15f * colorNormalizationFactor), G = (ushort)(0.2f * colorNormalizationFactor), B = (ushort)(0.35f * colorNormalizationFactor), }, }; DeviceBuffer vb = RF.CreateBuffer( new BufferDescription((uint)(Unsafe.SizeOf <UIntVertexAttribs.Vertex>() * vertices.Length), BufferUsage.VertexBuffer)); GD.UpdateBuffer(vb, 0, vertices); GD.UpdateBuffer(infoBuffer, 0, new UIntVertexAttribs.Info { ColorNormalizationFactor = colorNormalizationFactor }); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetFramebuffer(framebuffer); cl.SetFullViewports(); cl.SetFullScissorRects(); cl.ClearColorTarget(0, RgbaFloat.Black); cl.SetPipeline(pipeline); cl.SetVertexBuffer(0, vb); cl.SetGraphicsResourceSet(0, set); cl.Draw((uint)vertices.Length); cl.SetFramebuffer(GD.SwapchainFramebuffer); cl.ClearColorTarget(0, RgbaFloat.Red); cl.CopyTexture(target, staging); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read); foreach (VertexCPU_UShort vertex in vertices) { uint x = (uint)vertex.Position.X; uint y = (uint)vertex.Position.Y; if (GD.BackendType == GraphicsBackend.OpenGL) { y = framebuffer.Height - y - 1; } RgbaFloat expectedColor = new RgbaFloat( vertex.R / (float)colorNormalizationFactor, vertex.G / (float)colorNormalizationFactor, vertex.B / (float)colorNormalizationFactor, 1); Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
public ContentManager( Game game, FileSystem fileSystem, GraphicsDevice graphicsDevice, SageGame sageGame, WndCallbackResolver wndCallbackResolver) { using (GameTrace.TraceDurationEvent("ContentManager()")) { _game = game; _fileSystem = fileSystem; GraphicsDevice = graphicsDevice; SageGame = sageGame; Language = LanguageUtility.ReadCurrentLanguage(game.Definition, fileSystem.RootDirectory); IniDataContext = new IniDataContext(fileSystem, sageGame); DataContext = new DataContext(); SubsystemLoader = Content.SubsystemLoader.Create(game.Definition, _fileSystem, IniDataContext); switch (sageGame) { // Only load these INI files for a subset of games, because we can't parse them for others yet. case SageGame.CncGenerals: case SageGame.CncGeneralsZeroHour: case SageGame.Bfme: case SageGame.Bfme2: case SageGame.Bfme2Rotwk: SubsystemLoader.Load(Subsystem.Core); // TODO: Move this somewhere else. // Subsystem.Core should load mouse and water config, but that isn't the case with at least BFME2. IniDataContext.LoadIniFile(@"Data\INI\Mouse.ini"); IniDataContext.LoadIniFile(@"Data\INI\Water.ini"); IniDataContext.LoadIniFile(@"Data\INI\AudioSettings.ini"); break; default: break; } // TODO: Defer subsystem loading until necessary switch (sageGame) { // Only load these INI files for a subset of games, because we can't parse them for others yet. case SageGame.CncGenerals: case SageGame.CncGeneralsZeroHour: case SageGame.Bfme: case SageGame.Bfme2: case SageGame.Bfme2Rotwk: SubsystemLoader.Load(Subsystem.Players); SubsystemLoader.Load(Subsystem.ParticleSystems); SubsystemLoader.Load(Subsystem.ObjectCreation); SubsystemLoader.Load(Subsystem.Multiplayer); SubsystemLoader.Load(Subsystem.LinearCampaign); break; default: break; } _contentLoaders = new Dictionary <Type, ContentLoader> { { typeof(Model), AddDisposable(new ModelLoader()) }, { typeof(Scene3D), AddDisposable(new MapLoader()) }, { typeof(Texture), AddDisposable(new TextureLoader(graphicsDevice)) }, { typeof(Window), AddDisposable(new WindowLoader(this, wndCallbackResolver, Language)) }, { typeof(AptWindow), AddDisposable(new AptLoader()) }, }; _cachedObjects = new Dictionary <string, object>(); TranslationManager = Translation.TranslationManager.Instance; Translation.TranslationManager.LoadGameStrings(fileSystem, Language, sageGame); _cachedFonts = new Dictionary <FontKey, Font>(); var linearClampSamplerDescription = SamplerDescription.Linear; linearClampSamplerDescription.AddressModeU = SamplerAddressMode.Clamp; linearClampSamplerDescription.AddressModeV = SamplerAddressMode.Clamp; linearClampSamplerDescription.AddressModeW = SamplerAddressMode.Clamp; LinearClampSampler = AddDisposable( graphicsDevice.ResourceFactory.CreateSampler(ref linearClampSamplerDescription)); var pointClampSamplerDescription = SamplerDescription.Point; pointClampSamplerDescription.AddressModeU = SamplerAddressMode.Clamp; pointClampSamplerDescription.AddressModeV = SamplerAddressMode.Clamp; pointClampSamplerDescription.AddressModeW = SamplerAddressMode.Clamp; PointClampSampler = AddDisposable( graphicsDevice.ResourceFactory.CreateSampler(ref pointClampSamplerDescription)); NullTexture = AddDisposable(graphicsDevice.ResourceFactory.CreateTexture(TextureDescription.Texture2D(1, 1, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled))); _cachedNullStructuredBuffers = new Dictionary <uint, DeviceBuffer>(); SolidWhiteTexture = AddDisposable(graphicsDevice.CreateStaticTexture2D( 1, 1, 1, new TextureMipMapData( new byte[] { 255, 255, 255, 255 }, 4, 4, 1, 1), PixelFormat.R8_G8_B8_A8_UNorm)); ShaderResources = AddDisposable(new ShaderResourceManager(graphicsDevice, SolidWhiteTexture)); WndImageLoader = AddDisposable(new WndImageLoader(this, new MappedImageLoader(this))); _fallbackFonts = new FontCollection(); var assembly = Assembly.GetExecutingAssembly(); var fontStream = assembly.GetManifestResourceStream($"OpenSage.Content.Fonts.{_fallbackEmbeddedFont}-Regular.ttf"); _fallbackFonts.Install(fontStream); fontStream = assembly.GetManifestResourceStream($"OpenSage.Content.Fonts.{_fallbackEmbeddedFont}-Bold.ttf"); _fallbackFonts.Install(fontStream); } }
protected override Texture CreateTextureCore(ref TextureDescription description) { return(new MTLTexture(ref description, _gd)); }
protected override void CreateResources(ResourceFactory factory) { _vertexLayout = new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float3), new VertexElementDescription("UV", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2), new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.Float3), new VertexElementDescription("Normal", VertexElementSemantic.Normal, VertexElementFormat.Float3)); using (Stream planeModelStream = OpenEmbeddedAssetStream("plane2.dae")) { _planeModel = new Model( GraphicsDevice, factory, planeModelStream, "dae", _vertexLayout, new Model.ModelCreateInfo(new Vector3(0.5f, 0.5f, 0.5f), Vector2.One, Vector3.Zero)); } using (Stream dragonModelStream = OpenEmbeddedAssetStream("chinesedragon.dae")) { _dragonModel = new Model( GraphicsDevice, factory, dragonModelStream, "dae", _vertexLayout, new Model.ModelCreateInfo(new Vector3(0.3f, -0.3f, 0.3f), Vector2.One, Vector3.Zero)); } using (Stream colorMapStream = OpenEmbeddedAssetStream("darkmetal_bc3_unorm.ktx")) { _colorMap = KtxFile.LoadTexture( GraphicsDevice, factory, colorMapStream, PixelFormat.BC3_UNorm); } _colorView = factory.CreateTextureView(_colorMap); _offscreenColor = factory.CreateTexture(TextureDescription.Texture2D( OffscreenWidth, OffscreenHeight, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled)); _offscreenView = factory.CreateTextureView(_offscreenColor); Texture offscreenDepth = factory.CreateTexture(TextureDescription.Texture2D( OffscreenWidth, OffscreenHeight, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil)); _offscreenFB = factory.CreateFramebuffer(new FramebufferDescription(offscreenDepth, _offscreenColor)); ShaderSetDescription phongShaders = new ShaderSetDescription( new[] { _vertexLayout }, new[] { LoadShader(factory, "Phong", ShaderStages.Vertex, "VS"), LoadShader(factory, "Phong", ShaderStages.Fragment, "FS") }); ResourceLayout phongLayout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("UBO", ResourceKind.UniformBuffer, ShaderStages.Vertex))); GraphicsPipelineDescription pd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.DepthOnlyLessEqual, new RasterizerStateDescription(FaceCullMode.Front, PolygonFillMode.Solid, FrontFace.Clockwise, true, false), PrimitiveTopology.TriangleList, phongShaders, phongLayout, _offscreenFB.OutputDescription); _offscreenPipeline = factory.CreateGraphicsPipeline(pd); pd.Outputs = GraphicsDevice.SwapchainFramebuffer.OutputDescription; pd.RasterizerState = RasterizerStateDescription.Default; _dragonPipeline = factory.CreateGraphicsPipeline(pd); ResourceLayout mirrorLayout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("UBO", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("ReflectionMap", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("ReflectionMapSampler", ResourceKind.Sampler, ShaderStages.Fragment), new ResourceLayoutElementDescription("ColorMap", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("ColorMapSampler", ResourceKind.Sampler, ShaderStages.Fragment))); ShaderSetDescription mirrorShaders = new ShaderSetDescription( new[] { _vertexLayout }, new[] { LoadShader(factory, "Mirror", ShaderStages.Vertex, "VS"), LoadShader(factory, "Mirror", ShaderStages.Fragment, "FS") }); GraphicsPipelineDescription mirrorPD = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.DepthOnlyLessEqual, new RasterizerStateDescription(FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, true, false), PrimitiveTopology.TriangleList, mirrorShaders, mirrorLayout, GraphicsDevice.SwapchainFramebuffer.OutputDescription); _mirrorPipeline = factory.CreateGraphicsPipeline(ref mirrorPD); _uniformBuffers_vsShared = factory.CreateBuffer(new BufferDescription(208, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); _uniformBuffers_vsMirror = factory.CreateBuffer(new BufferDescription(208, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); _uniformBuffers_vsOffScreen = factory.CreateBuffer(new BufferDescription(208, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); _offscreenResourceSet = factory.CreateResourceSet(new ResourceSetDescription(phongLayout, _uniformBuffers_vsOffScreen)); _dragonResourceSet = factory.CreateResourceSet(new ResourceSetDescription(phongLayout, _uniformBuffers_vsShared)); _mirrorResourceSet = factory.CreateResourceSet(new ResourceSetDescription(mirrorLayout, _uniformBuffers_vsMirror, _offscreenView, GraphicsDevice.LinearSampler, _colorView, GraphicsDevice.Aniso4xSampler)); _cl = factory.CreateCommandList(); }
public GpuSurface CreateGpuSurface(bool isFrameworkInternal, uint width, uint height, PixelFormat pixelFormat, bool hasDepthBuffer, SamplerType samplerType, uint numberMipLevels, bool isGpuToCpuStagingTexture) { if (width == 0 || height == 0) { throw new Yak2DException("Internal Framework Exception: GpuSurfaceFactory, texture size must be non 0"); } if (numberMipLevels == 0) { numberMipLevels = 1; } var texture = _components.Factory.CreateTexture(TextureDescription.Texture2D( width, height, numberMipLevels, 1, pixelFormat, isGpuToCpuStagingTexture ? TextureUsage.Staging : TextureUsage.RenderTarget | TextureUsage.Sampled, TextureSampleCountConverter.ConvertYakToVeldrid(_components.SwapChainFramebufferSampleCount) )); var view = isGpuToCpuStagingTexture ? null : _components.Factory.CreateTextureView(texture); var depthStencil = hasDepthBuffer ? _components.Factory.CreateTexture(TextureDescription.Texture2D( width, height, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil )) : null; var buffer = isGpuToCpuStagingTexture ? null : _components.Factory.CreateFramebuffer(new FramebufferDescription(hasDepthBuffer ? depthStencil : null, texture)); Sampler wrap = null; Sampler mirror = null; switch (samplerType) { case SamplerType.Anisotropic: wrap = _anisotropicSamplerWrap; mirror = _anisotropicSamplerMirror; break; case SamplerType.Linear: wrap = _linearSamplerWrap; mirror = _linearSamplerMirror; break; case SamplerType.Point: wrap = _pointSamplerWrap; mirror = _pointSamplerMirror; break; case SamplerType.PointMagLinearMin: wrap = _pointMagLinearMinSamplerWrap; mirror = _pointMagLinearMinSamplerMirror; break; } var resourceSet_wrap = isGpuToCpuStagingTexture ? null : _components.Factory.CreateResourceSet(new ResourceSetDescription( _cachedTextureResourceLayout, view, wrap )); var resourceSet_mirror = isGpuToCpuStagingTexture ? null : _components.Factory.CreateResourceSet(new ResourceSetDescription( _cachedTextureResourceLayout, view, mirror )); return(new GpuSurface { Type = isFrameworkInternal ? GpuSurfaceType.RenderTarget | GpuSurfaceType.Internal : GpuSurfaceType.RenderTarget | GpuSurfaceType.User, Texture = texture, TextureView = view, Framebuffer = buffer, ResourceSet_TexWrap = resourceSet_wrap, ResourceSet_TexMirror = resourceSet_mirror }); }
private void CreateDepthTexture() { if (_depthFormat.HasValue) { _depthAttachment?.Target.Dispose(); VkTexture depthTexture = (VkTexture)_gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D( Math.Max(1, _scExtent.width), Math.Max(1, _scExtent.height), 1, 1, _depthFormat.Value, TextureUsage.DepthStencil)); _depthAttachment = new FramebufferAttachment(depthTexture, 0); } }
protected override Texture CreateTextureCore(ulong nativeTexture, ref TextureDescription description) => Track(_factory.CreateTexture(nativeTexture, description));
protected override Texture CreateTextureCore(ref TextureDescription description) => Track(_factory.CreateTexture(description));
public virtual void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, GraphicsSystem sc) { ResourceFactory factory = gd.ResourceFactory; ProjectionMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); ViewMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer0 = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer0.Name = "LightViewProjectionBuffer0"; LightViewProjectionBuffer1 = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer1.Name = "LightViewProjectionBuffer1"; LightViewProjectionBuffer2 = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer2.Name = "LightViewProjectionBuffer2"; DepthLimitsBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <DepthCascadeLimits>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightInfoBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <DirectionalLightInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); CameraInfoBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <CameraInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); if (Camera != null) { UpdateCameraBuffers(cl); } PointLightsBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <PointLightsInfo.Blittable>(), BufferUsage.UniformBuffer)); PointLightsInfo pli = new PointLightsInfo(); pli.NumActiveLights = 4; pli.PointLights = new PointLightInfo[4] { new PointLightInfo { Color = new Vector3(1f, 1f, 1f), Position = new Vector3(-50, 5, 0), Range = 75f }, new PointLightInfo { Color = new Vector3(1f, .75f, .9f), Position = new Vector3(0, 5, 0), Range = 100f }, new PointLightInfo { Color = new Vector3(1f, 1f, 0.6f), Position = new Vector3(50, 5, 0), Range = 40f }, new PointLightInfo { Color = new Vector3(0.75f, 0.75f, 1f), Position = new Vector3(25, 5, 45), Range = 150f }, }; cl.UpdateBuffer(PointLightsBuffer, 0, pli.GetBlittable()); TextureSamplerResourceLayout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("SourceTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("SourceSampler", ResourceKind.Sampler, ShaderStages.Fragment))); uint ReflectionMapSize = 2048; ReflectionColorTexture = factory.CreateTexture(TextureDescription.Texture2D(ReflectionMapSize, ReflectionMapSize, 12, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled | TextureUsage.GenerateMipmaps)); ReflectionDepthTexture = factory.CreateTexture(TextureDescription.Texture2D(ReflectionMapSize, ReflectionMapSize, 1, 1, PixelFormat.R32_Float, TextureUsage.DepthStencil)); ReflectionColorView = factory.CreateTextureView(ReflectionColorTexture); ReflectionFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(ReflectionDepthTexture, ReflectionColorTexture)); ReflectionViewProjBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); MirrorClipPlaneBuffer = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer)); gd.UpdateBuffer(MirrorClipPlaneBuffer, 0, new ClipPlaneInfo(MirrorMesh.Plane, true)); NoClipPlaneBuffer = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer)); gd.UpdateBuffer(NoClipPlaneBuffer, 0, new ClipPlaneInfo()); RecreateWindowSizedResources(gd, cl); ShadowMaps.CreateDeviceResources(gd); }
/// <summary> /// Determines the number of image array entries and pixel size. /// </summary> /// <param name="description">The texture description.</param> /// <param name="nImages">The number of entries in the image array.</param> /// <param name="pixelSize">The total pixel size.</param> private static void DetermineImages(TextureDescription description, out int nImages, out int pixelSize) { Debug.Assert(description.Width > 0 && description.Height > 0 && description.Depth > 0); Debug.Assert(description.ArraySize > 0); Debug.Assert(description.MipLevels > 0); pixelSize = 0; nImages = 0; switch (description.Dimension) { case TextureDimension.Texture1D: case TextureDimension.Texture2D: case TextureDimension.TextureCube: for (int item = 0; item < description.ArraySize; item++) { int w = description.Width; int h = description.Height; for (int level = 0; level < description.MipLevels; level++) { int rowPitch, slicePitch; TextureHelper.ComputePitch(description.Format, w, h, out rowPitch, out slicePitch, ComputePitchFlags.None); pixelSize += slicePitch; nImages++; if (h > 1) h >>= 1; if (w > 1) w >>= 1; } } break; case TextureDimension.Texture3D: { int w = description.Width; int h = description.Height; int d = description.Depth; for (int level = 0; level < description.MipLevels; level++) { int rowPitch, slicePitch; TextureHelper.ComputePitch(description.Format, w, h, out rowPitch, out slicePitch, ComputePitchFlags.None); for (int slice = 0; slice < d; slice++) { pixelSize += slicePitch; nImages++; } if (h > 1) h >>= 1; if (w > 1) w >>= 1; if (d > 1) d >>= 1; } } break; default: Debug.Fail("Unexpected texture dimension"); break; } }
public void RecreateWindowSizedResources(GraphicsDevice gd, CommandList cl) { MainSceneColorTexture?.Dispose(); MainSceneDepthTexture?.Dispose(); MainSceneResolvedColorTexture?.Dispose(); MainSceneResolvedColorView?.Dispose(); MainSceneViewResourceSet?.Dispose(); MainSceneFramebuffer?.Dispose(); DuplicatorTarget0?.Dispose(); DuplicatorTarget1?.Dispose(); DuplicatorTargetView0?.Dispose(); DuplicatorTargetView1?.Dispose(); DuplicatorTargetSet0?.Dispose(); DuplicatorTargetSet1?.Dispose(); DuplicatorFramebuffer?.Dispose(); ResourceFactory factory = gd.ResourceFactory; TextureSampleCount mainSceneSampleCountCapped = (TextureSampleCount)Math.Min( (int)gd.GetSampleCountLimit(PixelFormat.R8_G8_B8_A8_UNorm, false), (int)MainSceneSampleCount); TextureDescription mainColorDesc = TextureDescription.Texture2D( gd.SwapchainFramebuffer.Width, gd.SwapchainFramebuffer.Height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled, mainSceneSampleCountCapped); MainSceneColorTexture = factory.CreateTexture(ref mainColorDesc); if (mainSceneSampleCountCapped != TextureSampleCount.Count1) { mainColorDesc.SampleCount = TextureSampleCount.Count1; MainSceneResolvedColorTexture = factory.CreateTexture(ref mainColorDesc); } else { MainSceneResolvedColorTexture = MainSceneColorTexture; } MainSceneResolvedColorView = factory.CreateTextureView(MainSceneResolvedColorTexture); MainSceneDepthTexture = factory.CreateTexture(TextureDescription.Texture2D( gd.SwapchainFramebuffer.Width, gd.SwapchainFramebuffer.Height, 1, 1, PixelFormat.R32_Float, TextureUsage.DepthStencil, mainSceneSampleCountCapped)); MainSceneFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(MainSceneDepthTexture, MainSceneColorTexture)); MainSceneViewResourceSet = factory.CreateResourceSet(new ResourceSetDescription(TextureSamplerResourceLayout, MainSceneResolvedColorView, gd.PointSampler)); TextureDescription colorTargetDesc = TextureDescription.Texture2D( gd.SwapchainFramebuffer.Width, gd.SwapchainFramebuffer.Height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled); DuplicatorTarget0 = factory.CreateTexture(ref colorTargetDesc); DuplicatorTargetView0 = factory.CreateTextureView(DuplicatorTarget0); DuplicatorTarget1 = factory.CreateTexture(ref colorTargetDesc); DuplicatorTargetView1 = factory.CreateTextureView(DuplicatorTarget1); DuplicatorTargetSet0 = factory.CreateResourceSet(new ResourceSetDescription(TextureSamplerResourceLayout, DuplicatorTargetView0, gd.PointSampler)); DuplicatorTargetSet1 = factory.CreateResourceSet(new ResourceSetDescription(TextureSamplerResourceLayout, DuplicatorTargetView1, gd.PointSampler)); FramebufferDescription fbDesc = new FramebufferDescription(null, DuplicatorTarget0, DuplicatorTarget1); DuplicatorFramebuffer = factory.CreateFramebuffer(ref fbDesc); }
/// <summary> /// Validates the texture. /// </summary> /// <param name="description">The texture description.</param> /// <exception cref="ArgumentException"> /// The <paramref name="description"/> is invalid. /// </exception> /// <exception cref="NotSupportedException"> /// The specified format is not supported. /// </exception> private static void ValidateTexture(TextureDescription description) { if (!TextureHelper.IsValid(description.Format)) throw new ArgumentException("The specified texture format is not supported.", "description"); if (TextureHelper.IsPalettized(description.Format)) throw new ArgumentException("Palettized texture formats are not supported.", "description"); switch (description.Dimension) { case TextureDimension.Texture1D: if (description.Width <= 0 || description.Height != 1 || description.Depth != 1 || description.ArraySize <= 0) throw new ArgumentException("Invalid texture description.", "description"); //if (TextureHelper.IsVideo(description.Format)) // throw new NotSupportedException("Video formats are not supported."); if (!TextureHelper.ValidateMipLevels(description.Width, 1, description.MipLevels)) throw new ArgumentException("Invalid number of mipmap levels.", "description"); break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: if (description.Width <= 0 || description.Height <= 0 || description.Depth != 1 || description.ArraySize <= 0) throw new ArgumentException("Invalid texture description.", "description"); if (description.Dimension == TextureDimension.TextureCube) { if ((description.ArraySize % 6) != 0) throw new ArgumentException("All six faces need to be specified for cube maps.", "description"); //if (TextureHelper.IsVideo(description.Format)) // throw new NotSupportedException("Video formats are not supported."); } if (!TextureHelper.ValidateMipLevels(description.Width, description.Height, description.MipLevels)) throw new ArgumentException("Invalid number of mipmaps levels.", "description"); break; case TextureDimension.Texture3D: if (description.Width <= 0 || description.Height <= 0 || description.Depth <= 0 || description.ArraySize != 1) throw new ArgumentException("Invalid texture description.", "description"); //if (TextureHelper.IsVideo(description.Format) || TextureHelper.IsPlanar(description.Format) // || TextureHelper.IsDepthStencil(description.Format)) // throw new NotSupportedException("The specified texture format is not supported."); if (!TextureHelper.ValidateMipLevels(description.Width, description.Height, description.Depth, description.MipLevels)) throw new ArgumentException("Invalid number of mipmaps levels.", "description"); break; default: throw new NotSupportedException("The specified texture dimension is not supported."); } }
//-------------------------------------------------------------- /// <summary> /// Converts an XNA <see cref="TextureContent"/> to a DigitalRune <see cref="Texture"/>. /// </summary> /// <param name="textureContent">The <see cref="TextureContent"/>.</param> /// <returns>The <see cref="Texture"/>.</returns> public static Texture ToTexture(TextureContent textureContent) { SurfaceFormat surfaceFormat; var bitmapContent0 = textureContent.Faces[0][0]; if (!bitmapContent0.TryGetFormat(out surfaceFormat)) throw new InvalidContentException("Invalid surface format.", textureContent.Identity); var texture2DContent = textureContent as Texture2DContent; if (texture2DContent != null) { var description = new TextureDescription { Dimension = TextureDimension.Texture2D, Width = bitmapContent0.Width, Height = bitmapContent0.Height, Depth = 1, MipLevels = texture2DContent.Mipmaps.Count, ArraySize = 1, Format = surfaceFormat.ToDataFormat() }; var texture = new Texture(description); for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var bitmapContent = texture2DContent.Mipmaps[mipIndex]; var image = texture.Images[texture.GetImageIndex(mipIndex, 0, 0)]; Buffer.BlockCopy(bitmapContent.GetPixelData(), 0, image.Data, 0, image.Data.Length); } return texture; } var textureCubeContent = textureContent as TextureCubeContent; if (textureCubeContent != null) { var description = new TextureDescription { Dimension = TextureDimension.TextureCube, Width = bitmapContent0.Width, Height = bitmapContent0.Height, Depth = 1, MipLevels = textureCubeContent.Faces[0].Count, ArraySize = 6, Format = surfaceFormat.ToDataFormat() }; var texture = new Texture(description); for (int faceIndex = 0; faceIndex < 6; faceIndex++) { for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var bitmapContent = textureCubeContent.Faces[faceIndex][mipIndex]; var image = texture.Images[texture.GetImageIndex(mipIndex, faceIndex, 0)]; Buffer.BlockCopy(bitmapContent.GetPixelData(), 0, image.Data, 0, image.Data.Length); } } return texture; } var texture3DContent = textureContent as Texture3DContent; if (texture3DContent != null) { var description = new TextureDescription { Dimension = TextureDimension.Texture3D, Width = bitmapContent0.Width, Height = bitmapContent0.Height, Depth = texture3DContent.Faces.Count, MipLevels = texture3DContent.Faces[0].Count, ArraySize = 1, Format = surfaceFormat.ToDataFormat() }; var texture = new Texture(description); for (int zIndex = 0; zIndex < description.Depth; zIndex++) { for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++) { var bitmapContent = texture3DContent.Faces[zIndex][mipIndex]; var image = texture.Images[texture.GetImageIndex(mipIndex, 0, zIndex)]; Buffer.BlockCopy(bitmapContent.GetPixelData(), 0, image.Data, 0, image.Data.Length); } } return texture; } throw new InvalidOperationException("Invalid texture dimension."); }