Exemplo n.º 1
0
        public SwapchainD3D12(
            D3D12GraphicsDevice device,
            SwapChainDescriptor descriptor,
            int backbufferCount)
            : base(device, descriptor, device.DXGIFactory, device.GraphicsQueue, backbufferCount, backbufferCount)
        {
            _backbufferTextures = new TextureD3D12[backbufferCount];
            for (int i = 0; i < backbufferCount; i++)
            {
                var backBufferTexture = _swapChain.GetBuffer <ID3D12Resource>(i);
                var d3dTextureDesc    = backBufferTexture.Description;
                var textureDescriptor = TextureDescriptor.Texture2D(
                    (int)d3dTextureDesc.Width,
                    d3dTextureDesc.Height,
                    d3dTextureDesc.MipLevels,
                    d3dTextureDesc.DepthOrArraySize,
                    d3dTextureDesc.Format.FromDirectXPixelFormat(),
                    D3D12Convert.Convert(d3dTextureDesc.Flags),
                    (SampleCount)d3dTextureDesc.SampleDescription.Count);

                _backbufferTextures[i] = new TextureD3D12(device, textureDescriptor, backBufferTexture);
            }

            // Configure base.
            Configure(descriptor);
        }
 public void Reset(Texture2D texture, int numFrameRows, int numFrameColumns)
 {
     TextureDescriptor.Reset(texture);
     _numFrames          = numFrameRows * numFrameColumns;
     _numFrameColumns    = numFrameColumns;
     _referenceFrameRect = new Rectangle(0, 0, texture.Width / numFrameColumns, texture.Height / numFrameRows);
 }
Exemplo n.º 3
0
 private HostShaderCacheEntry()
 {
     Header   = new HostShaderCacheEntryHeader();
     CBuffers = new BufferDescriptor[0];
     SBuffers = new BufferDescriptor[0];
     Textures = new TextureDescriptor[0];
     Images   = new TextureDescriptor[0];
 }
Exemplo n.º 4
0
        public SelectionManager(Editor e)
        {
            myEditor = e;

            TextureDescriptor td = new TextureDescriptor("../data/textures/circle.png");

            mySelectTexture = Renderer.resourceManager.getResource(td) as Texture;
        }
Exemplo n.º 5
0
 public TextureAttribute(long type, TextureDescriptor textureDescription, float offsetU, float offsetV, float scaleU, float scaleV, int uvIndex = 0) : this(type, textureDescription)
 {
     this.offsetU = offsetU;
     this.offsetV = offsetV;
     this.scaleU  = scaleU;
     this.scaleV  = scaleV;
     this.uvIndex = uvIndex;
 }
Exemplo n.º 6
0
 public TextureAttribute(long type) : base(type)
 {
     if (!@is(type))
     {
         throw new Exception("Invalid type specified");
     }
     textureDescription = new TextureDescriptor();
 }
Exemplo n.º 7
0
        private static void DeclareImages(CodeGenContext context, StructuredProgramInfo info)
        {
            Dictionary <string, AstTextureOperation> images = new Dictionary <string, AstTextureOperation>();

            foreach (AstTextureOperation texOp in info.Images.OrderBy(x => x.Handle))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

                if (!images.TryAdd(imageName, texOp))
                {
                    // Ensure that all texture operations share the same format.
                    // This avoid errors like mismatched formats.
                    texOp.Format = images[imageName].Format;

                    continue;
                }

                string layout = texOp.Format.ToGlslFormat();

                if (!string.IsNullOrEmpty(layout))
                {
                    layout = "layout(" + layout + ") ";
                }

                string imageTypeName = GetImageTypeName(texOp.Type, texOp.Format.GetComponentType());

                context.AppendLine("uniform " + layout + imageTypeName + " " + imageName + ";");
            }

            foreach (KeyValuePair <string, AstTextureOperation> kv in images)
            {
                string imageName = kv.Key;

                AstTextureOperation texOp = kv.Value;

                if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        string indexExpr = NumberFormatter.FormatInt(index);

                        string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                        var desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    var desc = new TextureDescriptor(imageName, texOp.Type, texOp.Handle);

                    context.ImageDescriptors.Add(desc);
                }
            }
        }
Exemplo n.º 8
0
 public bool set(int uniform, TextureDescriptor textureDesc)
 {
     if (locations[uniform] < 0)
     {
         return(false);
     }
     program.setUniformi(locations[uniform], context.textureBinder.bind(textureDesc));
     return(true);
 }
Exemplo n.º 9
0
        private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
        {
            Dictionary <string, AstTextureOperation> samplers = new Dictionary <string, AstTextureOperation>();

            foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                if (!samplers.TryAdd(samplerName, texOp))
                {
                    continue;
                }

                string samplerTypeName = GetSamplerTypeName(texOp.Type);

                context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";");
            }

            foreach (KeyValuePair <string, AstTextureOperation> kv in samplers)
            {
                string samplerName = kv.Key;

                AstTextureOperation texOp = kv.Value;

                TextureDescriptor desc;

                if ((texOp.Flags & TextureFlags.Bindless) != 0)
                {
                    AstOperand operand = texOp.GetSource(0) as AstOperand;

                    desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);

                    context.TextureDescriptors.Add(desc);
                }
                else if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        string indexExpr = NumberFormatter.FormatInt(index);

                        string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                        desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle);

                    context.TextureDescriptors.Add(desc);
                }
            }
        }
Exemplo n.º 10
0
        private static void DeclareImages(CodeGenContext context, StructuredProgramInfo info)
        {
            HashSet <string> images = new HashSet <string>();

            foreach (AstTextureOperation texOp in info.Images.OrderBy(x => x.Handle))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

                if ((texOp.Flags & TextureFlags.Bindless) != 0 || !images.Add(imageName))
                {
                    continue;
                }

                int firstBinding = -1;

                if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        int binding = context.Config.Counts.IncrementImagesCount();

                        if (firstBinding < 0)
                        {
                            firstBinding = binding;
                        }

                        var desc = new TextureDescriptor(binding, texOp.Type, texOp.Format, texOp.CbufSlot, texOp.Handle + index * 2);

                        context.ImageDescriptors.Add(desc);
                    }
                }
                else
                {
                    firstBinding = context.Config.Counts.IncrementImagesCount();

                    var desc = new TextureDescriptor(firstBinding, texOp.Type, texOp.Format, texOp.CbufSlot, texOp.Handle);

                    context.ImageDescriptors.Add(desc);
                }

                string layout = texOp.Format.ToGlslFormat();

                if (!string.IsNullOrEmpty(layout))
                {
                    layout = ", " + layout;
                }

                string imageTypeName = texOp.Type.ToGlslImageType(texOp.Format.GetComponentType());

                context.AppendLine($"layout (binding = {firstBinding}{layout}) uniform {imageTypeName} {imageName};");
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Queries the format of a given texture.
        /// </summary>
        /// <param name="descriptor">Descriptor of the texture from the texture pool</param>
        /// <returns>The texture format</returns>
        private static TextureFormat QueryTextureFormat(TextureDescriptor descriptor)
        {
            if (!FormatTable.TryGetTextureFormat(descriptor.UnpackFormat(), descriptor.UnpackSrgb(), out FormatInfo formatInfo))
            {
                return TextureFormat.Unknown;
            }

            return formatInfo.Format switch
            {
                Format.R8Unorm           => TextureFormat.R8Unorm,
                Format.R8Snorm           => TextureFormat.R8Snorm,
                Format.R8Uint            => TextureFormat.R8Uint,
                Format.R8Sint            => TextureFormat.R8Sint,
                Format.R16Float          => TextureFormat.R16Float,
                Format.R16Unorm          => TextureFormat.R16Unorm,
                Format.R16Snorm          => TextureFormat.R16Snorm,
                Format.R16Uint           => TextureFormat.R16Uint,
                Format.R16Sint           => TextureFormat.R16Sint,
                Format.R32Float          => TextureFormat.R32Float,
                Format.R32Uint           => TextureFormat.R32Uint,
                Format.R32Sint           => TextureFormat.R32Sint,
                Format.R8G8Unorm         => TextureFormat.R8G8Unorm,
                Format.R8G8Snorm         => TextureFormat.R8G8Snorm,
                Format.R8G8Uint          => TextureFormat.R8G8Uint,
                Format.R8G8Sint          => TextureFormat.R8G8Sint,
                Format.R16G16Float       => TextureFormat.R16G16Float,
                Format.R16G16Unorm       => TextureFormat.R16G16Unorm,
                Format.R16G16Snorm       => TextureFormat.R16G16Snorm,
                Format.R16G16Uint        => TextureFormat.R16G16Uint,
                Format.R16G16Sint        => TextureFormat.R16G16Sint,
                Format.R32G32Float       => TextureFormat.R32G32Float,
                Format.R32G32Uint        => TextureFormat.R32G32Uint,
                Format.R32G32Sint        => TextureFormat.R32G32Sint,
                Format.R8G8B8A8Unorm     => TextureFormat.R8G8B8A8Unorm,
                Format.R8G8B8A8Snorm     => TextureFormat.R8G8B8A8Snorm,
                Format.R8G8B8A8Uint      => TextureFormat.R8G8B8A8Uint,
                Format.R8G8B8A8Sint      => TextureFormat.R8G8B8A8Sint,
                Format.R16G16B16A16Float => TextureFormat.R16G16B16A16Float,
                Format.R16G16B16A16Unorm => TextureFormat.R16G16B16A16Unorm,
                Format.R16G16B16A16Snorm => TextureFormat.R16G16B16A16Snorm,
                Format.R16G16B16A16Uint  => TextureFormat.R16G16B16A16Uint,
                Format.R16G16B16A16Sint  => TextureFormat.R16G16B16A16Sint,
                Format.R32G32B32A32Float => TextureFormat.R32G32B32A32Float,
                Format.R32G32B32A32Uint  => TextureFormat.R32G32B32A32Uint,
                Format.R32G32B32A32Sint  => TextureFormat.R32G32B32A32Sint,
                Format.R10G10B10A2Unorm  => TextureFormat.R10G10B10A2Unorm,
                Format.R10G10B10A2Uint   => TextureFormat.R10G10B10A2Uint,
                Format.R11G11B10Float    => TextureFormat.R11G11B10Float,
                _                        => TextureFormat.Unknown
            };
        }
Exemplo n.º 12
0
        private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
        {
            HashSet <string> samplers = new HashSet <string>();

            // Texture instructions other than TextureSample (like TextureSize)
            // may have incomplete sampler type information. In those cases,
            // we prefer instead the more accurate information from the
            // TextureSample instruction, if both are available.
            foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle * 2 + (x.Inst == Instruction.TextureSample ? 0 : 1)))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                if ((texOp.Flags & TextureFlags.Bindless) != 0 || !samplers.Add(samplerName))
                {
                    continue;
                }

                int firstBinding = -1;

                if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        int binding = context.Config.Counts.IncrementTexturesCount();

                        if (firstBinding < 0)
                        {
                            firstBinding = binding;
                        }

                        var desc = new TextureDescriptor(binding, texOp.Type, texOp.Format, texOp.CbufSlot, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    firstBinding = context.Config.Counts.IncrementTexturesCount();

                    var desc = new TextureDescriptor(firstBinding, texOp.Type, texOp.Format, texOp.CbufSlot, texOp.Handle);

                    context.TextureDescriptors.Add(desc);
                }

                string samplerTypeName = texOp.Type.ToGlslSamplerType();

                context.AppendLine($"layout (binding = {firstBinding}) uniform {samplerTypeName} {samplerName};");
            }
        }
Exemplo n.º 13
0
        private static void DeclareImages(CodeGenContext context, StructuredProgramInfo info)
        {
            Dictionary <string, AstTextureOperation> images = new Dictionary <string, AstTextureOperation>();

            foreach (AstTextureOperation texOp in info.Images.OrderBy(x => x.Handle))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

                if (!images.TryAdd(imageName, texOp))
                {
                    continue;
                }

                string imageTypeName = GetImageTypeName(texOp.Type);

                context.AppendLine("writeonly uniform " + imageTypeName + " " + imageName + ";");
            }

            foreach (KeyValuePair <string, AstTextureOperation> kv in images)
            {
                string imageName = kv.Key;

                AstTextureOperation texOp = kv.Value;

                if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        string indexExpr = NumberFormatter.FormatInt(index);

                        string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                        var desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    var desc = new TextureDescriptor(imageName, texOp.Type, texOp.Handle);

                    context.ImageDescriptors.Add(desc);
                }
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Reads the shader program info from the cache.
        /// </summary>
        /// <param name="dataReader">Cache data reader</param>
        /// <returns>Shader program info</returns>
        private static ShaderProgramInfo ReadShaderProgramInfo(ref BinarySerializer dataReader)
        {
            DataShaderInfo dataInfo = new DataShaderInfo();

            dataReader.ReadWithMagicAndSize(ref dataInfo, ShdiMagic);

            BufferDescriptor[]  cBuffers = new BufferDescriptor[dataInfo.CBuffersCount];
            BufferDescriptor[]  sBuffers = new BufferDescriptor[dataInfo.SBuffersCount];
            TextureDescriptor[] textures = new TextureDescriptor[dataInfo.TexturesCount];
            TextureDescriptor[] images   = new TextureDescriptor[dataInfo.ImagesCount];

            for (int index = 0; index < dataInfo.CBuffersCount; index++)
            {
                dataReader.ReadWithMagicAndSize(ref cBuffers[index], BufdMagic);
            }

            for (int index = 0; index < dataInfo.SBuffersCount; index++)
            {
                dataReader.ReadWithMagicAndSize(ref sBuffers[index], BufdMagic);
            }

            for (int index = 0; index < dataInfo.TexturesCount; index++)
            {
                dataReader.ReadWithMagicAndSize(ref textures[index], TexdMagic);
            }

            for (int index = 0; index < dataInfo.ImagesCount; index++)
            {
                dataReader.ReadWithMagicAndSize(ref images[index], TexdMagic);
            }

            return(new ShaderProgramInfo(
                       cBuffers,
                       sBuffers,
                       textures,
                       images,
                       dataInfo.Stage,
                       dataInfo.UsesInstanceId,
                       dataInfo.UsesRtLayer,
                       dataInfo.ClipDistancesWritten,
                       dataInfo.FragmentOutputMap));
        }
Exemplo n.º 15
0
        private static TextureDescriptor[] GetTextureOrImageDescriptors(Dictionary <TextureInfo, TextureMeta> dict, Func <int> getBindingCallback)
        {
            var descriptors = new TextureDescriptor[dict.Count];

            int i = 0;

            foreach (var kv in dict.OrderBy(x => x.Key.Indexed).OrderBy(x => x.Key.Handle))
            {
                var info = kv.Key;
                var meta = kv.Value;

                int binding = getBindingCallback();

                descriptors[i] = new TextureDescriptor(binding, meta.Type, info.Format, info.CbufSlot, info.Handle);
                descriptors[i].SetFlag(meta.UsageFlags);
                i++;
            }

            return(descriptors);
        }
Exemplo n.º 16
0
        private int bindTexture(TextureDescriptor textureDesc, bool rebind)
        {
            int       idx, result;
            GLTexture texture = textureDesc.texture;

            reused = false;

            switch (method)
            {
            case 0:
                result = offset + (idx = bindTextureRoundRobin(texture));
                break;

            case 1:
                result = offset + (idx = bindTextureWeighted(texture));
                break;

            default:
                return(-1);
            }

            if (reused)
            {
                reuseCount++;
                if (rebind)
                {
                    texture.bind(result);
                }
                else
                {
                    GL.ActiveTexture(TextureUnit.Texture0 + result);
                }
            }
            else
            {
                bindCount++;
            }
            texture.unsafeSetWrap(textureDesc.uWrap, textureDesc.vWrap);
            texture.unsafeSetFilter(textureDesc.minFilter, textureDesc.magFilter);
            return(result);
        }
Exemplo n.º 17
0
        public TextureD3D12(
            D3D12GraphicsDevice device,
            ref TextureDescriptor descriptor,
            ID3D12Resource nativeTexture)
            : base(device, ref descriptor)
        {
            DXGIFormat = descriptor.Format.ToDirectX();
            if (nativeTexture == null)
            {
                ResourceFlags resourceFlags = ResourceFlags.None;
                if ((descriptor.Usage & TextureUsage.ShaderWrite) != 0)
                {
                    resourceFlags |= ResourceFlags.AllowUnorderedAccess;
                }

                // A multisampled resource must have either D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET or
                // D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL set in D3D12_RESOURCE_DESC::Flags.
                if ((descriptor.Usage & TextureUsage.RenderTarget) != 0 ||
                    descriptor.Samples > 0 ||
                    !PixelFormatUtil.IsCompressed(descriptor.Format))
                {
                    if (PixelFormatUtil.IsDepthStencilFormat(descriptor.Format))
                    {
                        if ((descriptor.Usage & TextureUsage.ShaderRead) == 0)
                        {
                            resourceFlags |= ResourceFlags.DenyShaderResource;
                        }

                        resourceFlags |= ResourceFlags.AllowDepthStencil;
                    }
                    else
                    {
                        resourceFlags |= ResourceFlags.AllowRenderTarget;
                    }
                }
            }
            else
            {
                Resource = nativeTexture;
            }
        }
Exemplo n.º 18
0
        public void Extract(SubAssetKey key, TextureDescriptor texDesc)
        {
            if (Textures.ContainsKey(key))
            {
                return;
            }

            // write converted texture
            if (m_subAssets.TryGetValue(key, out var texture) && texture is Texture2D tex2D)
            {
                var targetPath = m_textureDirectory.Child($"{key.Name}.png");
                File.WriteAllBytes(targetPath.FullPath, tex2D.EncodeToPNG().ToArray());
                targetPath.ImportAsset();

                Textures.Add(key, targetPath);
            }
            else
            {
                throw new Exception($"{key} is not converted.");
            }
        }
Exemplo n.º 19
0
            public Model(BinaryReader reader, uint address, uint nameOffset, int index)
            {
                this.index      = index;
                this.address    = address;
                this.nameOffset = nameOffset;

                // Recover name
                reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
                name = GetName(reader);

                //Debug.LogFormat("{0}::{1}", Index, Name);

                // GCMF
                gcmf = new GCMF(reader, address);

                // Observe why null GCMFs occur
                if (gcmf.TextureCount > 0)
                {
                    // MATERIAL DESCRIPTION
                    textureDescriptor = new TextureDescriptor[gcmf.TextureCount];
                    for (int i = 0; i < textureDescriptor.Length; i++)
                    {
                        textureDescriptor[i] = new TextureDescriptor(reader);
                    }

                    // VERTEX STRIPS
                    // TEMP: NOT INCLUDING MT_TL
                    vertexStrips = new GC_VertexStripCollection[gcmf.Count_MT];
                    if (gcmf.Count_MT > 0)
                    {
                        for (int i = 0; i < gcmf.Count_MT; i++)
                        {
                            vertexStrips[i] = new GC_VertexStripCollection(reader, gcmf);
                        }
                    }
                }
            }
Exemplo n.º 20
0
 private static bool TryGetNormalTexture(GltfData data, glTFMaterial src, out (SubAssetKey, TextureDescriptor) pair)
 {
     try
     {
         pair = GltfPbrTextureImporter.NormalTexture(data, src);
         return(true);
     }
     catch (NullReferenceException)
     {
         pair = default;
         return(false);
     }
     catch (ArgumentOutOfRangeException)
     {
         pair = default;
         return(false);
     }
 }
Exemplo n.º 21
0
 public TextureAttribute(long type, TextureDescriptor textureDescription) : this(type)
 {
     this.textureDescription.set(textureDescription);
 }
Exemplo n.º 22
0
        /// <summary>
        /// VRM-1 の thumbnail テクスチャー。gltf.textures ではなく gltf.images の参照であることに注意(sampler等の設定が無い)
        /// </summary>
        public static bool TryGetMetaThumbnailTextureImportParam(GltfData data, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, out (SubAssetKey, TextureDescriptor) value)
        {
            if (vrm?.Meta?.ThumbnailImage == null)
            {
                value = default;
                return(false);
            }

            var imageIndex = vrm.Meta.ThumbnailImage.Value;
            var gltfImage  = data.GLTF.images[imageIndex];
            var name       = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfImage.name, gltfImage.uri);

            GetTextureBytesAsync getThumbnailImageBytesAsync = () =>
            {
                var bytes = data.GLTF.GetImageBytes(data.Storage, imageIndex);
                return(Task.FromResult(GltfTextureImporter.ToArray(bytes)));
            };
            var texDesc = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, Vector2.zero, Vector2.one, default, TextureImportTypes.sRGB, default, default,
Exemplo n.º 23
0
        /// <summary>
        /// VRM-1 の thumbnail テクスチャー。gltf.textures ではなく gltf.images の参照であることに注意(sampler等の設定が無い)
        /// </summary>
        public static bool TryGetMetaThumbnailTextureImportParam(GltfData data, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, out (SubAssetKey, TextureDescriptor) value)
        {
            if (vrm?.Meta?.ThumbnailImage == null)
            {
                value = default;
                return(false);
            }
            var thumbnailImage = vrm.Meta.ThumbnailImage;

            if (!thumbnailImage.HasValue)
            {
                value = default;
                return(false);
            }
            var imageIndex = thumbnailImage.Value;

            if (imageIndex < 0 || imageIndex >= data.GLTF.images.Count)
            {
                value = default;
                return(false);
            }

            var gltfImage = data.GLTF.images[imageIndex];

            // data.GLTF.textures は前処理によりユニーク性がある
            // unique な名前を振り出す
            var used      = new HashSet <string>(data.GLTF.textures.Select(x => x.name));
            var imageName = gltfImage.name;

            if (string.IsNullOrEmpty(imageName))
            {
                imageName = THUMBNAIL_NAME;
            }
            var uniqueName = GlbLowLevelParser.FixNameUnique(used, imageName);

            value = GltfTextureImporter.CreateSrgbFromOnlyImage(data, imageIndex, uniqueName, gltfImage.uri);
            return(true);
        }
Exemplo n.º 24
0
        public static bool TryGetTextureFromMaterialProperty(GltfData data, glTF_VRM_Material vrmMaterial, string textureKey, out (SubAssetKey, TextureDescriptor) texture)
        {
            // 任意の shader の import を許容する
            if (/*vrmMaterial.shader == MToon.Utils.ShaderName &&*/ vrmMaterial.textureProperties.TryGetValue(textureKey, out var textureIdx))
            {
                var(offset, scale) = (new Vector2(0, 0), new Vector2(1, 1));
                if (TryGetTextureOffsetAndScale(vrmMaterial, textureKey, out var os))
                {
                    offset = os.offset;
                    scale  = os.scale;
                }

                switch (textureKey)
                {
                case MToon.Utils.PropBumpMap:
                    texture = GltfTextureImporter.CreateNormal(data, textureIdx, offset, scale);
                    break;

                default:
                    texture = GltfTextureImporter.CreateSrgb(data, textureIdx, offset, scale);
                    break;
                }
                return(true);
            }

            texture = default;
            return(false);
        }
Exemplo n.º 25
0
            private void ReadSectionData(SectionBase section, Header ptclHeader, FileReader reader)
            {
                if (section.BinaryDataOffset != NullOffset)
                {
                    using (reader.TemporarySeek(section.BinaryDataOffset + section.Position, SeekOrigin.Begin))
                    {
                        BinaryDataBytes = reader.ReadBytes((int)section.SectionSize);
                    }
                }

                switch (section.Signature)
                {
                case "TEXR":
                    section.Text = "Texture Info";
                    BinaryData   = new TEXR();

                    if (SubSectionCount > 0)
                    {
                        //Set the data block first!
                        reader.Seek(SubSectionOffset + section.Position, SeekOrigin.Begin);
                        var dataBlockSection = new SectionBase();
                        dataBlockSection.Read(reader, ptclHeader, "GX2B");

                        if (dataBlockSection.BinaryDataOffset != NullOffset)
                        {
                            reader.Seek(dataBlockSection.BinaryDataOffset + dataBlockSection.Position, SeekOrigin.Begin);
                            ((TEXR)BinaryData).data = reader.ReadBytes((int)dataBlockSection.SectionSize);
                        }
                    }

                    reader.Seek(BinaryDataOffset + section.Position, SeekOrigin.Begin);
                    ((TEXR)BinaryData).Read(reader, ptclHeader);

                    break;

                case "SHDB":
                    reader.Seek(BinaryDataOffset + section.Position, SeekOrigin.Begin);
                    section.Text = "GTX Shader";
                    reader.ReadBytes((int)section.SectionSize);
                    break;

                case "EMTR":
                    reader.Seek(BinaryDataOffset + 16 + section.Position, SeekOrigin.Begin);
                    Text = reader.ReadString(BinaryStringFormat.ZeroTerminated);

                    reader.Seek(BinaryDataOffset + 16 + 64 + section.Position, SeekOrigin.Begin);
                    BinaryData = new Emitter();
                    ((Emitter)BinaryData).Read(reader, ptclHeader);
                    break;

                case "ESTA":
                    section.Text = "Emitter Sets";
                    break;

                case "ESET":
                    byte[] Padding = reader.ReadBytes(16);
                    section.Text = reader.ReadString(BinaryStringFormat.ZeroTerminated);
                    break;

                case "GRTF":
                    if (section.BinaryDataOffset != NullOffset)
                    {
                        reader.Seek(section.BinaryDataOffset + section.Position, SeekOrigin.Begin);
                        BinaryData = new BNTX();
                        ((BNTX)BinaryData).FileName = "textures.bntx";
                        ((BNTX)BinaryData).Load(new MemoryStream(reader.ReadBytes((int)section.SectionSize)));
                        ((BNTX)BinaryData).IFileInfo.InArchive = true;
                        Nodes.Add(((BNTX)BinaryData));
                    }
                    break;

                case "PRMA":
                    break;

                case "ESFT":
                    reader.Seek(28, SeekOrigin.Current);
                    int StringSize = reader.ReadInt32();
                    section.Text = reader.ReadString(StringSize, Encoding.ASCII);
                    break;

                case "GRSN":
                    section.Text = "Shaders";

                    if (section.BinaryDataOffset != NullOffset)
                    {
                        reader.Seek(section.BinaryDataOffset + section.Position, SeekOrigin.Begin);
                        BinaryData = reader.ReadBytes((int)section.SectionSize);
                    }
                    break;

                case "GRSC":
                    section.Text = "Shaders 2";
                    if (section.BinaryDataOffset != NullOffset)
                    {
                        reader.Seek(section.BinaryDataOffset + section.Position, SeekOrigin.Begin);
                        BinaryData = reader.ReadBytes((int)section.SectionSize);
                    }
                    break;

                case "G3PR":
                    if (section.BinaryDataOffset != NullOffset)
                    {
                        reader.Seek(section.BinaryDataOffset + section.Position, SeekOrigin.Begin);
                        BinaryData = new BFRES();
                        ((BFRES)BinaryData).FileName = "model.bfres";
                        ((BFRES)BinaryData).Load(new MemoryStream(reader.ReadBytes((int)section.SectionSize)));
                        ((BFRES)BinaryData).IFileInfo           = new IFileInfo();
                        ((BFRES)BinaryData).IFileInfo.InArchive = true;
                        Nodes.Add(((BFRES)BinaryData));
                    }
                    break;

                case "GTNT":
                    if (section.BinaryDataOffset != NullOffset)
                    {
                        foreach (var node in Parent.Nodes)
                        {
                            if (node is BNTX)
                            {
                                BNTX bntx = (BNTX)node;

                                reader.Seek(section.BinaryDataOffset + section.Position, SeekOrigin.Begin);
                                for (int i = 0; i < bntx.Textures.Count; i++)
                                {
                                    var texDescriptor = new TextureDescriptor();
                                    Nodes.Add(texDescriptor);
                                    texDescriptor.Read(reader, bntx);
                                }
                            }
                        }
                    }
                    break;
                }
            }
        private static bool TryGetThumbnailTexture(GltfData data, glTF_VRM_extensions vrm, out (SubAssetKey, TextureDescriptor) texture)
        {
            if (vrm.meta.texture > -1)
            {
                texture = GltfTextureImporter.CreateSRGB(data, vrm.meta.texture, Vector2.zero, Vector2.one);
                return(true);
            }

            texture = default;
            return(false);
        }
Exemplo n.º 27
0
        private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
        {
            Dictionary <string, AstTextureOperation> samplers = new Dictionary <string, AstTextureOperation>();

            // Texture instructions other than TextureSample (like TextureSize)
            // may have incomplete sampler type information. In those cases,
            // we prefer instead the more accurate information from the
            // TextureSample instruction, if both are available.
            foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle * 2 + (x.Inst == Instruction.TextureSample ? 0 : 1)))
            {
                string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize);

                string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                if (!samplers.TryAdd(samplerName, texOp))
                {
                    continue;
                }

                string samplerTypeName = GetSamplerTypeName(texOp.Type);

                context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";");
            }

            foreach (KeyValuePair <string, AstTextureOperation> kv in samplers)
            {
                string samplerName = kv.Key;

                AstTextureOperation texOp = kv.Value;

                TextureDescriptor desc;

                if ((texOp.Flags & TextureFlags.Bindless) != 0)
                {
                    AstOperand operand = texOp.GetSource(0) as AstOperand;

                    desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);

                    context.TextureDescriptors.Add(desc);
                }
                else if ((texOp.Type & SamplerType.Indexed) != 0)
                {
                    for (int index = 0; index < texOp.ArraySize; index++)
                    {
                        string indexExpr = NumberFormatter.FormatInt(index);

                        string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

                        desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2);

                        context.TextureDescriptors.Add(desc);
                    }
                }
                else
                {
                    desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle);

                    context.TextureDescriptors.Add(desc);
                }
            }
        }
Exemplo n.º 28
0
        protected Material convertMaterial(ModelMaterial mtl, TextureProvider textureProvider)
        {
            Material result = new Material();

            result.id = mtl.id;
            if (mtl.ambient != default(Color))
            {
                result.set(new ColorAttribute(ColorAttribute.Ambient, mtl.ambient));
            }
            if (mtl.diffuse != default(Color))
            {
                result.set(new ColorAttribute(ColorAttribute.Diffuse, mtl.diffuse));
            }
            if (mtl.specular != default(Color))
            {
                result.set(new ColorAttribute(ColorAttribute.Specular, mtl.specular));
            }
            if (mtl.emissive != default(Color))
            {
                result.set(new ColorAttribute(ColorAttribute.Emissive, mtl.emissive));
            }
            if (mtl.reflection != default(Color))
            {
                result.set(new ColorAttribute(ColorAttribute.Reflection, mtl.reflection));
            }
            if (mtl.shininess > 0f)
            {
                result.set(new FloatAttribute(FloatAttribute.Shininess, mtl.shininess));
            }
            if (mtl.opacity != 1.0f)
            {
                result.set(new BlendingAttribute(true, BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, mtl.opacity));
            }

            var textures = new Dictionary <string, Texture>();

            // FIXME uvScaling/uvTranslation totally ignored
            if (mtl.textures != null)
            {
                foreach (ModelTexture tex in mtl.textures)
                {
                    Texture texture;
                    if (textures.ContainsKey(tex.fileName))
                    {
                        texture = textures[tex.fileName];
                    }
                    else
                    {
                        texture = textureProvider.load(tex.fileName);
                        textures.Add(tex.fileName, texture);
                        disposables.Add(texture);
                    }

                    var descriptor = new TextureDescriptor(texture);
                    descriptor.minFilter = texture.getMinFilter();
                    descriptor.magFilter = texture.getMagFilter();
                    descriptor.uWrap     = texture.getUWrap();
                    descriptor.vWrap     = texture.getVWrap();

                    float offsetU = tex.uvTranslation == null ? 0f : tex.uvTranslation.X;
                    float offsetV = tex.uvTranslation == null ? 0f : tex.uvTranslation.Y;
                    float scaleU  = tex.uvScaling == null ? 1f : tex.uvScaling.X;
                    float scaleV  = tex.uvScaling == null ? 1f : tex.uvScaling.Y;

                    switch (tex.usage)
                    {
                    case ModelTexture.USAGE_DIFFUSE:
                        result.set(new TextureAttribute(TextureAttribute.Diffuse, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;

                    case ModelTexture.USAGE_SPECULAR:
                        result.set(new TextureAttribute(TextureAttribute.Specular, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;

                    case ModelTexture.USAGE_BUMP:
                        result.set(new TextureAttribute(TextureAttribute.Bump, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;

                    case ModelTexture.USAGE_NORMAL:
                        result.set(new TextureAttribute(TextureAttribute.Normal, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;

                    case ModelTexture.USAGE_AMBIENT:
                        result.set(new TextureAttribute(TextureAttribute.Ambient, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;

                    case ModelTexture.USAGE_EMISSIVE:
                        result.set(new TextureAttribute(TextureAttribute.Emissive, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;

                    case ModelTexture.USAGE_REFLECTION:
                        result.set(new TextureAttribute(TextureAttribute.Reflection, descriptor, offsetU, offsetV, scaleU, scaleV));
                        break;
                    }
                }
            }

            return(result);
        }
Exemplo n.º 29
0
        public static string TextureSample(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless     = (texOp.Flags & TextureFlags.Bindless) != 0;
            bool isGather       = (texOp.Flags & TextureFlags.Gather) != 0;
            bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
            bool intCoords      = (texOp.Flags & TextureFlags.IntCoords) != 0;
            bool hasLodBias     = (texOp.Flags & TextureFlags.LodBias) != 0;
            bool hasLodLevel    = (texOp.Flags & TextureFlags.LodLevel) != 0;
            bool hasOffset      = (texOp.Flags & TextureFlags.Offset) != 0;
            bool hasOffsets     = (texOp.Flags & TextureFlags.Offsets) != 0;

            bool isArray       = (texOp.Type & SamplerType.Array) != 0;
            bool isIndexed     = (texOp.Type & SamplerType.Indexed) != 0;
            bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
            bool isShadow      = (texOp.Type & SamplerType.Shadow) != 0;

            // This combination is valid, but not available on GLSL.
            // For now, ignore the LOD level and do a normal sample.
            // TODO: How to implement it properly?
            if (hasLodLevel && isArray && isShadow)
            {
                hasLodLevel = false;
            }

            string texCall = intCoords ? "texelFetch" : "texture";

            if (isGather)
            {
                texCall += "Gather";
            }
            else if (hasDerivatives)
            {
                texCall += "Grad";
            }
            else if (hasLodLevel && !intCoords)
            {
                texCall += "Lod";
            }

            if (hasOffset)
            {
                texCall += "Offset";
            }
            else if (hasOffsets)
            {
                texCall += "Offsets";
            }

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return(GetSoureExpr(context, texOp.GetSource(srcIndex++), type));
            }

            string indexExpr = null;

            if (isIndexed)
            {
                indexExpr = Src(VariableType.S32);
            }

            string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

            texCall += "(" + samplerName;

            int coordsCount = texOp.Type.GetDimensions();

            int pCount = coordsCount;

            int arrayIndexElem = -1;

            if (isArray)
            {
                arrayIndexElem = pCount++;
            }

            // The sampler 1D shadow overload expects a
            // dummy value on the middle of the vector, who knows why...
            bool hasDummy1DShadowElem = texOp.Type == (SamplerType.Texture1D | SamplerType.Shadow);

            if (hasDummy1DShadowElem)
            {
                pCount++;
            }

            if (isShadow && !isGather)
            {
                pCount++;
            }

            // On textureGather*, the comparison value is
            // always specified as an extra argument.
            bool hasExtraCompareArg = isShadow && isGather;

            if (pCount == 5)
            {
                pCount = 4;

                hasExtraCompareArg = true;
            }

            void Append(string str)
            {
                texCall += ", " + str;
            }

            VariableType coordType = intCoords ? VariableType.S32 : VariableType.F32;

            string AssemblePVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        if (arrayIndexElem == index)
                        {
                            elems[index] = Src(VariableType.S32);

                            if (!intCoords)
                            {
                                elems[index] = "float(" + elems[index] + ")";
                            }
                        }
                        else if (index == 1 && hasDummy1DShadowElem)
                        {
                            elems[index] = NumberFormatter.FormatFloat(0);
                        }
                        else
                        {
                            elems[index] = Src(coordType);
                        }
                    }

                    string prefix = intCoords ? "i" : string.Empty;

                    return(prefix + "vec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(coordType));
                }
            }

            string ApplyScaling(string vector)
            {
                if (intCoords)
                {
                    int index = context.FindTextureDescriptorIndex(texOp);

                    if ((context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) &&
                        (texOp.Flags & TextureFlags.Bindless) == 0 &&
                        texOp.Type != SamplerType.Indexed &&
                        pCount == 2)
                    {
                        return("Helper_TexelFetchScale(" + vector + ", " + index + ")");
                    }
                    else
                    {
                        // Resolution scaling cannot be applied to this texture right now.
                        // Flag so that we know to blacklist scaling on related textures when binding them.

                        TextureDescriptor descriptor = context.TextureDescriptors[index];
                        descriptor.Flags |= TextureUsageFlags.ResScaleUnsupported;
                        context.TextureDescriptors[index] = descriptor;
                    }
                }

                return(vector);
            }

            Append(ApplyScaling(AssemblePVector(pCount)));

            string AssembleDerivativesVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        elems[index] = Src(VariableType.F32);
                    }

                    return("vec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(VariableType.F32));
                }
            }

            if (hasExtraCompareArg)
            {
                Append(Src(VariableType.F32));
            }

            if (hasDerivatives)
            {
                Append(AssembleDerivativesVector(coordsCount)); // dPdx
                Append(AssembleDerivativesVector(coordsCount)); // dPdy
            }

            if (isMultisample)
            {
                Append(Src(VariableType.S32));
            }
            else if (hasLodLevel)
            {
                Append(Src(coordType));
            }

            string AssembleOffsetVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        elems[index] = Src(VariableType.S32);
                    }

                    return("ivec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(VariableType.S32));
                }
            }

            if (hasOffset)
            {
                Append(AssembleOffsetVector(coordsCount));
            }
            else if (hasOffsets)
            {
                texCall += $", ivec{coordsCount}[4](";

                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ")";
            }

            if (hasLodBias)
            {
                Append(Src(VariableType.F32));
            }

            // textureGather* optional extra component index,
            // not needed for shadow samplers.
            if (isGather && !isShadow)
            {
                Append(Src(VariableType.S32));
            }

            texCall += ")" + (isGather || !isShadow ? GetMask(texOp.Index) : "");

            return(texCall);
        }
Exemplo n.º 30
0
        public void Run()
        {
            try
            {
                // Load renderer
                renderer = RenderSystem.Load("OpenGL", debugger);

                // Create render context
                var contextDesc = new RenderContextDescriptor();
                {
                    contextDesc.VideoMode.Resolution.Width  = 800;
                    contextDesc.VideoMode.Resolution.Height = 600;
                    contextDesc.VideoMode.ColorBits         = 32;
                    contextDesc.VideoMode.DepthBits         = 24;
                    contextDesc.VideoMode.StencilBits       = 8;
                }
                context = renderer.CreateRenderContext(contextDesc);

                // Get context window
                var window = context.Surface;
                window.Shown = true;

                window.Title = $"LLGL for C# - Texturing ( {renderer.Name} )";

                // Print renderer information
                Console.WriteLine("Renderer Info:");
                var info = renderer.Info;
                {
                    Console.WriteLine($"  Renderer:         {info.RendererName}");
                    Console.WriteLine($"  Device:           {info.DeviceName}");
                    Console.WriteLine($"  Vendor:           {info.VendorName}");
                    Console.WriteLine($"  Shading Language: {info.ShadingLanguageName}");
                }

                // Create vertex buffer
                var vertexFormat = new VertexFormat();
                vertexFormat.AppendAttribute(new VertexAttribute("coord", Format.RG32Float));
                vertexFormat.AppendAttribute(new VertexAttribute("texCoord", Format.RG32Float));

                const float uvScale = 10.0f;

                var vertices = new Vertex[]
                {
                    new Vertex(-0.5f, -0.5f, 0.0f, uvScale),
                    new Vertex(-0.5f, +0.5f, 0.0f, 0.0f),
                    new Vertex(+0.5f, -0.5f, uvScale, uvScale),
                    new Vertex(+0.5f, +0.5f, uvScale, 0.0f),
                };

                var vertexBufferDesc = new BufferDescriptor();
                {
                    vertexBufferDesc.BindFlags           = BindFlags.VertexBuffer;
                    vertexBufferDesc.Size                = vertexFormat.Stride * (ulong)vertices.Length;
                    vertexBufferDesc.VertexBuffer.Format = vertexFormat;
                }
                var vertexBuffer = renderer.CreateBuffer(vertexBufferDesc, vertices);

                // Create shaders
                var vertShader = renderer.CreateShader(
                    new ShaderDescriptor(
                        type: ShaderType.Vertex,
                        sourceType: ShaderSourceType.CodeString,
                        source: @"
                            #version 330 core
                            in vec2 coord;
                            in vec2 texCoord;
                            out vec2 vTexCoord;
                            void main() {
                                gl_Position = vec4(coord, 0, 1);
                                vTexCoord = texCoord;
                            }
                        "
                        )
                    );
                var fragShader = renderer.CreateShader(
                    new ShaderDescriptor
                    (
                        type: ShaderType.Fragment,
                        sourceType: ShaderSourceType.CodeString,
                        source: @"
                            #version 330 core
                            in vec2 vTexCoord;
                            out vec4 fColor;
                            uniform sampler2D tex;
                            void main() {
                                fColor = texture(tex, vTexCoord);
                            }
                        "
                    )
                    );

                var shaderProgramDesc = new ShaderProgramDescriptor();
                {
                    shaderProgramDesc.VertexFormats.Add(vertexFormat);
                    shaderProgramDesc.VertexShader   = vertShader;
                    shaderProgramDesc.FragmentShader = fragShader;
                }
                var shaderProgram = renderer.CreateShaderProgram(shaderProgramDesc);

                if (shaderProgram.HasErrors)
                {
                    throw new Exception(shaderProgram.Report);
                }

                // Create pipeline layout
                var pipelineLayoutDesc = new PipelineLayoutDescriptor();
                {
                    pipelineLayoutDesc.Bindings.Add(
                        new BindingDescriptor(ResourceType.Texture, BindFlags.Sampled, StageFlags.FragmentStage, 0)
                        );
                    pipelineLayoutDesc.Bindings.Add(
                        new BindingDescriptor(ResourceType.Sampler, 0, StageFlags.FragmentStage, 0)
                        );
                }
                var pipelineLayout = renderer.CreatePipelineLayout(pipelineLayoutDesc);

                // Create graphics pipeline
                var pipelineDesc = new GraphicsPipelineDescriptor();
                {
                    pipelineDesc.ShaderProgram                 = shaderProgram;
                    pipelineDesc.PipelineLayout                = pipelineLayout;
                    pipelineDesc.PrimitiveTopology             = PrimitiveTopology.TriangleStrip;
                    pipelineDesc.Blend.Targets[0].BlendEnabled = true;
                }
                pipeline = renderer.CreateGraphicsPipeline(pipelineDesc);

                // Create texture
                var imageDesc = new SrcImageDescriptor <RGBA>();
                {
                    imageDesc.Format   = ImageFormat.RGBA;
                    imageDesc.DataType = DataType.UInt8;
                    imageDesc.Data     = new RGBA[4];
                    imageDesc.Data[0]  = new RGBA(255, 0, 0, 255);
                    imageDesc.Data[1]  = new RGBA(0, 255, 0, 255);
                    imageDesc.Data[2]  = new RGBA(0, 0, 0, 0);
                    imageDesc.Data[3]  = new RGBA(0, 0, 0, 0);
                }
                var textureDesc = new TextureDescriptor();
                {
                    textureDesc.Type   = TextureType.Texture2D;
                    textureDesc.Extent = new Extent3D(2, 2, 1);
                }
                var texture = renderer.CreateTexture(textureDesc, imageDesc);

                // Create sampler
                var samplerDesc = new SamplerDescriptor();
                {
                    samplerDesc.MagFilter = SamplerFilter.Nearest;
                }
                var sampler = renderer.CreateSampler(samplerDesc);

                // Create resource heap
                var resourceHeapDesc = new ResourceHeapDescriptor();
                {
                    resourceHeapDesc.PipelineLayout = pipelineLayout;
                    resourceHeapDesc.ResourceViews.Add(new ResourceViewDescriptor(texture));
                    resourceHeapDesc.ResourceViews.Add(new ResourceViewDescriptor(sampler));
                }
                var resourceHeap = renderer.CreateResourceHeap(resourceHeapDesc);

                // Get command queue
                cmdQueue  = renderer.CommandQueue;
                cmdBuffer = renderer.CreateCommandBuffer();

                cmdBuffer.SetClearColor(0.1f, 0.1f, 0.2f, 1.0f);

                // Render loop
                while (window.ProcessEvents())
                {
                    cmdBuffer.Begin();
                    {
                        cmdBuffer.SetVertexBuffer(vertexBuffer);

                        cmdBuffer.BeginRenderPass(context);
                        {
                            cmdBuffer.Clear(ClearFlags.Color);
                            cmdBuffer.SetViewport(new Viewport(0, 0, context.Resolution.Width, context.Resolution.Height));

                            cmdBuffer.SetGraphicsPipeline(pipeline);
                            cmdBuffer.SetGraphicsResourceHeap(resourceHeap);

                            cmdBuffer.Draw(4, 0);
                        }
                        cmdBuffer.EndRenderPass();
                    }
                    cmdBuffer.End();
                    cmdQueue.Submit(cmdBuffer);

                    context.Present();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.WriteLine("press any key to continue ...");
                Console.ReadKey();
            }
            finally
            {
                RenderSystem.Unload(renderer);
            }
        }