예제 #1
0
        public static ITexture2D LoadTexture(string filename, bool generateMips = false)
        {
            Assure.NotNull(filename);
            lock (staticMutationLock) {
                if (loadedTextures.ContainsKey(filename))
                {
                    ++textureRefCounts[filename];
                    return(loadedTextures[filename]);
                }
            }
            string fullFilePath = Path.Combine(MaterialsDir, filename);

            if (!File.Exists(fullFilePath))
            {
                throw new FileNotFoundException("Given texture file '" + filename + "' is not in the materials folder.");
            }

            ITexture2D loadedTex = null;

            GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
            GC.Collect(2, GCCollectionMode.Forced, true);

            if (generateMips)
            {
                var mipmapFilePath = Path.Combine(MaterialsDir, "Mipmaps\\", Path.GetFileNameWithoutExtension(filename)) + ".mipmap";
                if (File.Exists(mipmapFilePath))
                {
                    byte[] dataBytes = File.ReadAllBytes(mipmapFilePath);
                    int    texelTypeID;
                    uint   width, height;
                    using (MemoryStream ms = new MemoryStream(dataBytes)) {
                        BinaryReader br = new BinaryReader(ms);
                        texelTypeID = br.ReadInt32();
                        width       = br.ReadUInt32();
                        height      = br.ReadUInt32();
                    }

                    Type texelType         = TexelFormat.AllFormats.First(kvp => kvp.Value.ResourceFormatIndex == texelTypeID).Key;
                    var  createTex2DMethod =
                        typeof(TextureFactory)
                        .GetMethod("NewTexture2D", BindingFlags.Public | BindingFlags.Static)
                        .MakeGenericMethod(texelType);
                    dynamic builder = createTex2DMethod.Invoke(null, new object[0]);
                    loadedTex = builder.WithPermittedBindings(GPUBindings.ReadableShaderResource)
                                .WithUsage(ResourceUsage.Immutable)
                                .WithMipAllocation(true)
                                .WithWidth(width)
                                .WithHeight(height)
                                .WithInitialData(new ArraySlice <byte>(dataBytes, 4U))
                                .Create();
                }
                else
                {
                    Logger.Log("No mipmap data found for file '" + fullFilePath + "'; ");
                    LosgapSystem.InvokeOnMaster(() => {
                        ITexture2D singleTex = TextureFactory.LoadTexture2D().WithFilePath(fullFilePath)
                                               .WithPermittedBindings(GPUBindings.None)
                                               .WithUsage(ResourceUsage.StagingReadWrite)
                                               .Create();

                        ITexture2D mipGenTarget = ((dynamic)singleTex).Clone(false)
                                                  .WithMipAllocation(true)
                                                  .WithMipGenerationTarget(true)
                                                  .WithPermittedBindings(GPUBindings.RenderTarget | GPUBindings.ReadableShaderResource)
                                                  .WithUsage(ResourceUsage.Write)
                                                  .Create();

                        singleTex.GetType().GetMethod(
                            "CopyTo",
                            new[] { singleTex.GetType(), typeof(SubresourceBox), typeof(UInt32), typeof(UInt32), typeof(UInt32), typeof(UInt32) }
                            ).Invoke(
                            singleTex,
                            new object[] {
                            mipGenTarget, new SubresourceBox(0U, singleTex.Width, 0U, singleTex.Height), 0U, 0U, 0U, 0U
                        }
                            );
                        mipGenTarget.GenerateMips();

                        ITexture2D stagingTex = ((dynamic)mipGenTarget).Clone(false)
                                                .WithPermittedBindings(GPUBindings.None)
                                                .WithUsage(ResourceUsage.StagingReadWrite)
                                                .WithMipGenerationTarget(false)
                                                .Create();

                        mipGenTarget.CopyTo(stagingTex);

                        using (MemoryStream ms = new MemoryStream()) {
                            BinaryWriter bw = new BinaryWriter(ms);
                            bw.Write(TexelFormat.AllFormats[mipGenTarget.TexelFormat].ResourceFormatIndex);
                            bw.Write(stagingTex.Width);
                            bw.Write(stagingTex.Height);
                            bw.Write(stagingTex.ReadRaw());
                            ms.Seek(0L, SeekOrigin.Begin);
                            File.WriteAllBytes(mipmapFilePath, ms.ToArray());
                        }

                        loadedTex = ((dynamic)stagingTex).Clone(true)
                                    .WithPermittedBindings(GPUBindings.ReadableShaderResource)
                                    .WithUsage(ResourceUsage.Immutable)
                                    .Create();

                        singleTex.Dispose();
                        mipGenTarget.Dispose();
                        stagingTex.Dispose();
                    });
                }
            }
            else
            {
                loadedTex = TextureFactory.LoadTexture2D().WithFilePath(fullFilePath)
                            .WithPermittedBindings(GPUBindings.ReadableShaderResource)
                            .WithUsage(ResourceUsage.Immutable)
                            .Create();
            }

            lock (staticMutationLock) {
                loadedTextures[filename]   = loadedTex;
                textureRefCounts[filename] = 1U;
            }

            GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
            GC.Collect(2, GCCollectionMode.Forced, true);

            return(loadedTex);
        }