着色器可以在我的笔记本电脑上运行,但不能在我的台式机上运行

发布于 2025-01-10 01:58:54 字数 4216 浏览 0 评论 0原文

我昨天已经在统一答案上发布了这个问题,但也许这里有人可以提供帮助?我一直在尝试做一些涉及从本机插件获取图像(以 .dll 文件的形式)的事情。我将图像数据加载到本机缓冲区中,然后以结构化计算缓冲区的形式将其推送到 GPU。从那里,我使用着色器显示图像(基本上只是执行诸如 uint idx = x + y * width 之类的操作来获取正确的索引)。这在我的笔记本电脑上效果很好(忽略低分辨率,我降低了它以便能够检查每个像素的值;这正是它应该看起来的样子)。

working

但是当我在桌面上尝试它时,我得到的只是一团糟:

broken

它清楚地显示了一些东西,我几乎能够辨认出文本的轮廓(看起来我不仅仅是得到随机噪音)。但我似乎无法弄清楚这里出了什么问题。

到目前为止,我已经尝试过:

  • 在两台设备之间同步代码(完全相同)
  • 更改 Unity 版本(在两台机器上尝试过 2020.3.26f1 和 2021.2.12f)
  • 更新图形驱动程序
  • 检查 directx 版本(两台机器上的 DirectX 12) )
  • 更改编辑器游戏窗口分辨率
  • ,比较缓冲区的内容(ComputeBuffer.GetData 方法在两台机器上获取相同的完全有效的值
  • )两台机器上的项目(两个版本都在我的笔记本电脑上运行,但在我的台式机上损坏)

尤其是最后一点让我很困惑。我在两台机器上运行相同的可执行文件,它在带有集成显卡的笔记本电脑上运行(不确定这是否相关),但在带有更现代的专用 GPU 的台式机上运行不正常?我剩下的唯一想法是,我的台式机的 AMD GPU 可能会进行某种优化,而我的笔记本电脑的英特尔 GPU 上不会发生这种优化。关于我可以在 radeon 软件中尝试什么有什么想法吗?也许它甚至可能是某种错误(与统一或我的图形驱动程序有关)?

我会非常高兴任何关于这里可能出现问题的想法(因为我目前不知道)。抱歉,如果我的语法有时有点偏差,而不是母语人士。

编辑:这是我用来显示图像的着色器。

Shader "Hidden/ReadUnpacked"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
        SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            static const uint PACKED_SIZE = 3;
            static const uint PIXELS_PER_PACK = 4;
            static const uint BYTES_PER_PIXEL = 8;
            static const uint PERCISION = 0xFF;     // 0xFF = 2^8

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            struct packed4
            {
                uint p[PACKED_SIZE];
            };

            struct unpacked4
            {
                fixed4 p[PIXELS_PER_PACK];
            };

            StructuredBuffer<packed4> InputBuffer;
            uint ImgIdx;
            float2 Resolution;
            float2 TexelOffset;

            fixed unpackSingle(packed4 val, uint idx)
            {
                uint pid = idx / PIXELS_PER_PACK;                   // pixel index
                uint sid = idx % PIXELS_PER_PACK * BYTES_PER_PIXEL; // shift index

                return ((val.p[pid] >> sid) & PERCISION) / (half)PERCISION;
            }

            unpacked4 unpack(packed4 packed)
            {
                unpacked4 unpacked;
                half r, g, b;
                uint idx = 0;

                [unroll(PIXELS_PER_PACK)] for (uint i = 0; i < PIXELS_PER_PACK; i++)
                {
                    fixed4 upx = fixed4(0, 0, 0, 1);

                    [unroll(PACKED_SIZE)] for (uint j = 0; j < PACKED_SIZE; j++)
                    {
                        upx[j] = unpackSingle(packed, idx++);
                    }

                    unpacked.p[i] = upx;
                }

                return unpacked;
            }

            fixed4 samplePackedBuffer(float2 uv)
            {
                int2 tc = float2(uv.x, 1 - uv.y) * Resolution;
                uint idx = tc.x + tc.y * Resolution.x;      // image pixel index
                idx += Resolution.x * Resolution.y * ImgIdx;
                uint gid = floor(idx / PIXELS_PER_PACK);    // packed global index
                uint lid = idx % PIXELS_PER_PACK;           // packed local index

                packed4 ppx = InputBuffer[gid];
                unpacked4 upx = unpack(ppx);
                return upx.p[lid];
            }

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = samplePackedBuffer(i.uv);

                return col;
            }
            ENDCG
        }
    }
}

I already posted this question on unity answers yesterday, but maybe anyone here can help? I've been trying to do some stuff that involves getting an image from a native plugin (in the form of a .dll file). I load the image data into a native buffer and then push that to the gpu in the form of a structured compute buffer. From there, I display the image using a shader (basically just doing something like uint idx = x + y * width to get the correct index). And this works great on my laptop (ignore the low resolution, I lowered it to be able to inspect the values for each pixel; this is exactly how it's supposed to look).

working

But when I try it on my desktop, all I get is this mess:

broken

It's clearly displaying something, I'm almost able to make out contours of the text (it doesn't seem like I'm just getting random noise). But I can't seem to work out what's wrong here.

So far I've tried:

  • syncing the code across the two devices (it's excactly the same)
  • changing the unity version (tried 2020.3.26f1 and 2021.2.12f on both machines)
  • updating the graphics drivers
  • checking the directx version (DirectX 12 on both)
  • changing the editor game window resolution
  • comparing the contents of the buffer (the ComputeBuffer.GetData method is getting the same completely valid values on both machines)
  • building the project on both machines (both builds are working on my laptop and broken on my desktop)

Especially the last point really confused me. I'm running the same executable on both machines and it's working on my laptop with integrated graphics (not sure wether that could be relevant) but not on my desktop with a more modern dedicated gpu? The only idea I have left is that there might be some kind of optimization going on with my desktop's amd gpu that's not happening on my laptop's intel gpu. Any ideas on what I could try in the radeon software? Maybe it could even be some sort of bug (with unity or with my graphics driver)?

I'd be more than happy about any ideas on what could be the problem here (cause I have no clue at this point). And sorry if my grammar is a bit off at times, not a native speaker.

EDIT: Here's the shader I use to display the image.

Shader "Hidden/ReadUnpacked"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
        SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            static const uint PACKED_SIZE = 3;
            static const uint PIXELS_PER_PACK = 4;
            static const uint BYTES_PER_PIXEL = 8;
            static const uint PERCISION = 0xFF;     // 0xFF = 2^8

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            struct packed4
            {
                uint p[PACKED_SIZE];
            };

            struct unpacked4
            {
                fixed4 p[PIXELS_PER_PACK];
            };

            StructuredBuffer<packed4> InputBuffer;
            uint ImgIdx;
            float2 Resolution;
            float2 TexelOffset;

            fixed unpackSingle(packed4 val, uint idx)
            {
                uint pid = idx / PIXELS_PER_PACK;                   // pixel index
                uint sid = idx % PIXELS_PER_PACK * BYTES_PER_PIXEL; // shift index

                return ((val.p[pid] >> sid) & PERCISION) / (half)PERCISION;
            }

            unpacked4 unpack(packed4 packed)
            {
                unpacked4 unpacked;
                half r, g, b;
                uint idx = 0;

                [unroll(PIXELS_PER_PACK)] for (uint i = 0; i < PIXELS_PER_PACK; i++)
                {
                    fixed4 upx = fixed4(0, 0, 0, 1);

                    [unroll(PACKED_SIZE)] for (uint j = 0; j < PACKED_SIZE; j++)
                    {
                        upx[j] = unpackSingle(packed, idx++);
                    }

                    unpacked.p[i] = upx;
                }

                return unpacked;
            }

            fixed4 samplePackedBuffer(float2 uv)
            {
                int2 tc = float2(uv.x, 1 - uv.y) * Resolution;
                uint idx = tc.x + tc.y * Resolution.x;      // image pixel index
                idx += Resolution.x * Resolution.y * ImgIdx;
                uint gid = floor(idx / PIXELS_PER_PACK);    // packed global index
                uint lid = idx % PIXELS_PER_PACK;           // packed local index

                packed4 ppx = InputBuffer[gid];
                unpacked4 upx = unpack(ppx);
                return upx.p[lid];
            }

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = samplePackedBuffer(i.uv);

                return col;
            }
            ENDCG
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌无敌 2025-01-17 01:58:54

您应该检查所有其他 3D API(D3D11、Vulkan、OpenGL...)。

You should check all other 3D APIs (D3D11, Vulkan, OpenGL,...).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文