0

任务

对于我自己的 OpenGL 框架,当平台不支持它时,我正在尝试解压缩 PVRTC 纹理。为此,我下载了PVRTC-SDK并将 C++ 代码 1:1 转换为带有非托管代码的 C# 代码。

问题

简而言之:它不起作用,我不知道它的原因。我已经检查了两次代码,它似乎没问题,应该可以工作。有时我得到一个AccessViolationException,有时一个LoaderLockAccessViolationException不再发生,我的代码的另一部分出现错误。PVRTC 的颜色仍然是错误的。它看起来很奇怪,基本的笔画是可见的,但颜色是错误的。

代码

由于代码很大,我上传了它:

[C#] http://codeviewer.org/view/code:2a65

[C++] http://codeviewer.org/view/code:2a66

也是 C# 方法的调用代码,大小实际上与预期值匹配(所以源数组的图像值是完全正确width * height * 4bit的,输出大小是width * height * 4byte(所以压缩图像的 8 倍大小)。

private static unsafe Image ConvertPVRTC_RGBA8888(Image source)
{
    Int32 mipmapCount = source.HasMipmaps ? Image.GetMipmapCount(source.Width, source.Height) : 1;
    // Create a array with bytes for the target format
    Byte[] bytes = new Byte[RGBA8.GetMipMappedSize(0, mipmapCount, source.Width, source.Height)];


    fixed (Byte* pTarget = bytes)
    {
        fixed (Byte* pSource = source.GetData())
        {
            Int32 sourceOffset = 0;
            Int32 targetOffset = 0;

            for (Int32 i = 0; i < mipmapCount; i++)
            {
                // Calculate offsets
                Int32 sourceSize = source.Format.GetMipMappedSize(i, 1, source.Width, source.Height);
                Int32 targetSize = RGBA8.GetMipMappedSize(i, 1, source.Width, source.Height);

                // Decompress mipmapLevel
                PVRTC.DecompressPVRTC(pSource + sourceOffset, pTarget + targetOffset, GetMipmapSize(source.Width, i), GetMipmapSize(source.Height, i), source.Format.BitsPerPixel == 2);

                // Calculate pointer offset
                sourceOffset += sourceSize;
                targetOffset += targetSize;
            }
        }
    }
    return new Image(bytes, ImageFormat.RGBA8, source.Width, source.Height, source.HasMipmaps, source.IsCubemap);
}

想法

原始源代码不正确,或者我在翻译代码时遗漏了一些东西。无论如何,我需要一个解决方案并检查了两次源代码。

(如果有任何 C# 的源代码,我会使用它,但我找不到任何源代码)

4

1 回答 1

1

分而治之

在翻译代码的情况下,我建议增量测试代码。如果您可以为相同的代码段提供相同的数据(从最简单的方法开始),您就可以确定问题出在哪里。

类型尺寸

请注意,C# 中的 long 可能与 C++ 中的 long 不同。请注意,我没有查看您的代码以查看这是否是您的问题(工作量太大)。

调用约定

在 .NET 中调用不安全代码时,您可能必须指定调用方法(如何将参数推入堆栈和从堆栈中删除)。这些是我们在纯 .NET 解决方案中不必担心的事情,因为它们都是一样的。

于 2012-10-09T01:37:33.430 回答