Aros/开发者/文档/HIDD/Nouveau
NouveauBitMap 类包含一个 nouveau_bo 对象。此对象表示内存中一个可从 GPU 访问的缓冲区(VRAM 或 GART)。此 nouveau_bo 对象用于复制和填充等函数。
Nouveau 需要最小的 64x64 像素块大小才能使用加速传输。
UAE P96 到目前为止,picasso96 模拟始终使用 RGBFF_CHUNKY,它映射到 cybegraphics 中的 PIXFMT_BGR15,并通过 WirtePixelArray 将内容复制到显示窗口。当使用 WritePixelArray 时,会进行模式之间的转换。我根据其他驱动程序进行了此转换,因此此处不应有差异。现在它尝试通过 GetCyberIDAttr(modeID, CYBRIDATTR_PIXFMT) 获取像素格式,因此不应需要格式转换。从 PIXFMT_BGR15 到 24 位的转换不应该那么慢。此外,WritePixelArray 现在已加速,因此应该非常快。
当 3D 驱动程序想要将渲染缓冲区blit到位图上时,它需要获取位图背后的 nouveau_bo 并从其渲染缓冲区到此 nouveau_bo 对象进行 GPU 复制。渲染缓冲区始终与位图具有相同的像素格式,因为它是在创建 GL 上下文时基于传递的位图创建的。
我认为 Amiga 3D API 是 Warp3D,但我对此一无所知。在此上下文中,OpenGL 是一个外来的 API。
是的,mesa.library 是 AROS 特定的。我从未见过或使用过您提到的库,但我认为 AROSMesa API 可能与 StormMESA API 类似。我基于 Kalamatee 的工作构建了 AROSMesa API,该工作似乎基于 StormMESA。
从客户端的角度来看,使用 mesa.library 非常简单
- 创建一个窗口
- 调用 AROSMesaCreateContext 并将窗口和其他一些内容传递给它 -> 您将获得作为返回值的渲染上下文
- 调用 AROSMesaMakeCurrent 并将上下文传递给它,以便 AROSMesa 知道在哪里渲染
- 使用 glXXX 函数渲染一些内容
- 调用 AROSMesaSwapBuffers 将渲染缓冲区的内容绘制到您的窗口上
- 循环到 glXXX 函数
如果您正在寻找示例,请检查 /tests/mesa/mesasimplerendering.c 并检查 AROSMesaCreateContext() 代码。
此函数实际上负责设置“管道屏幕”——一个实际上用于渲染的实体。管道屏幕使用 gallium.library 管理,后者又使用 OOP 对象工作。
想知道在 SDL_Init() 和 SDL_Quit() 中做了什么;无论如何都不需要 peropenerbase 吗?嗯。SDL_VideoInit 操作全局变量“current_video”。但是 MorphOS 的 PowerSDL 似乎也做了同样的事情。
SDL 是否有一个上下文传递给每个函数,或者它是否依赖于上下文是“全局的”(就像 GL 一样)。如果是后者,您需要检查上下文是否可以是每个打开器(由多个任务共享)或上下文是否需要真正地每个任务。
是后者。我想知道这些问题是否是我的 MorphOS 的 PowerSDL 生成 ThreadServer 任务的原因。
或者,您可以使用我为 Mesa 使用的方法。Mesa 始终通过宏访问全局上下文,并且在 AROS 的情况下,此宏实际上使用我自己的非常简单的实现的“库端任务本地存储”。(参见 AROS/workbench/libs/mesa/src/aros/tls.[ch])。这样就不需要进行任何 GL API 更改。
目前 gallium.library 只知道两个后端
hidd.gallium.nouveau and hidd.gallium.softpipe (a software implementation).
此后端列表是硬编码的。
这里我看到了两个设计缺陷
- 后端列表硬编码。添加第三个后端(例如,用于 ATI)将需要修改 gallium.library。
- 后端对象(表示管道屏幕)在没有参数的情况下创建。它与任何显示驱动程序对象无关。
Nouveau 驱动程序的设计方式是在类静态数据中存储显卡信息(自动禁止使用多个显卡)。这是一个严重的缺陷。
为了克服这些问题,我建议做一些类似于位图管理的事情。我会在图形驱动程序类中添加一个方法,例如 moHidd_Gfx_NewPipeScreen。它将创建一个 hidd.gallium 子类的对象。实际的子类将取决于驱动程序(调用该方法的驱动程序)。
如果此方法返回 NULL,则表示此驱动程序不支持硬件加速 3D。在这种情况下,gallium.library 将使用 hidd.gallium.softpipe,就像现在一样。
gallium.library/CreatePipeScreen()
这种方式需要一个参数,例如 Screen*,或者更好的可能是 ViewPort*。它将从 ViewPort 的位图中获取显示驱动程序对象
OOP_Object *drv; OOP_Object *bm = vp->RasInfo->BitMap->Planes[0]; OOP_GetAttr(bm, aHidd_BitMap_GfxHidd, (IPTR *)&drv);
我不认为 moHidd_Gfx_NewPipeScreen 是正确的方法,它应该更像是 moHidd_Gfx_GalliumHiddObject。我现在也不愿意进行此更改,因为我不相信我知道 gallium.library 的所有用例。请记住,mesa.library 只是可能的客户端之一,并且您实际上不需要 Screen、ViewPort 或 BitMap 来使用 GPU。您只需要这些东西,如果您实际上想将渲染blit到 AROS 屏幕上。这就是为什么 3D 驱动程序与 2D 没有关联(就像现在的情况一样)。
这里有一个关于在 monitorclass 中实现 MM_Query3DSupport 的答案。我们需要添加 moHidd_Gfx_QueryHardware3D,并将像素格式对象作为参数。驱动程序将能够检查给定的像素格式并确定它是否支持硬件 3D。
对于 nouveau,moHidd_Gfx_QueryHardware3D 的实现应该是
if (card >= NV30 and bitsperpixelofmode >=16) return TRUE; else return FALSE;
我假设您将对 MM_Query3DSupport 进行以下实现
if (moHidd_Gfx_Query3DSupport) return MSQUERY3D_HWDRIVER; else if (bitsperpixelofmode >= 16) return MSQUERY3D_SWDRIVER; else return MSQUERY3D_NODRIVER;
在 monitorclass 中实现 MM_Query3DSupport 的答案。我们需要添加 moHidd_Gfx_QueryHardware3D,并将像素格式对象作为参数。驱动程序将能够检查给定的像素格式并确定它是否支持硬件 3D。我看到 softpipe.hidd 可以使用任何像素格式,因此我们可以安全地假设软件 3D 可以使用任何内容。
我看到 softpipe.hidd 可以使用任何像素格式,因此我们可以安全地假设软件 3D 可以使用任何内容。任何大于等于 16 位的内容。Mesa 不支持 256 色渲染。
您对此有何看法?如果可以,我将在规范中添加这些方法。您可以添加 moHidd_Gfx_QueryHardware3D,但我需要时间来考虑您提到的第一个方法。此外,第一个方法目前不需要用于您在 monitorclass 上的工作。
作为任何 HW GFX 驱动程序,Nouveau 目前只能与一张显卡一起工作。它是“旧式”驱动程序:) 实际上 CreatePipeScreen 结构 TagItem * 作为参数。这是有意为之,以便在“将来”通过创建额外的标签并添加它们的处理来实现您描述的内容。我想做一些与您描述非常相似的事情——CreatePipeScreen 将需要传递一个 BitMap 来创建合适的管道屏幕——我只是没有实现它。还要注意:这不会神奇地使 nouveau 支持多张显卡,而是在未来支持的更改。
信号量保护是在调用方级别完成的——例如 CopyBox 或 FillRect。我还向代码添加了明确的通知
AROS/workbench/hidds/hidd.nouveau/nouveau.conf AROS/workbench/hidds/hidd.nouveau/nouveau_intern.h AROS/workbench/hidds/hidd.nouveau/nouveaubitmapclass.c AROS/workbench/hidds/hidd.nouveau/nouveauclass.c AROS/workbench/hidds/hidd.nouveau/nouveaugalliumclass.c AROS/workbench/hidds/hidd.nouveau/nv04_accel.c AROS/workbench/hidds/hidd.nouveau/nv50_accel.c
/* NOTE: Assumes lock on bitmap is already made */ /* NOTE: Assumes buffer is not mapped */ BOOL HIDDNouveauNV04FillSolidRect(struct CardData * carddata, struct HIDDNouveauBitMapData * bmdata, ULONG minX, ULONG minY, ULONG maxX, ULONG maxY, ULONG drawmode, ULONG color)
如果像carddata->chan这样的东西是全局的(在位图之间共享),那么仅仅使用位图锁是不够的。一个作用于位图A的图形函数可能与作用于位图B的图形函数同时发生。
drm层本身负责同步对chan对象的访问。此外,命令缓冲区是针对每个调用者分配和执行的。映射/取消映射是关于获取缓冲区的VRAM地址。缓冲区分配在VRAM的某个位置,但根据需要,drm层可以将其移动到其他位置。为了获得缓冲区的“访问指针”,需要将其映射(nouveau_bo_map)。当缓冲区被映射时,它不能被移动,但加速函数也不能在映射的缓冲区上工作——因此,对于“指针”访问,我需要映射缓冲区,而对于加速访问,我需要取消映射它。
在其他地方,例如Linux/X11,情况有所不同,因为X11渲染函数仅由单个任务(X服务器)执行,但基本上移动Wanderer窗口,例如在mplayer中播放电影或在OWB中重新加载网页,应该会导致命令缓冲区损坏和GPU挂起或图形损坏(在最佳情况下)。
请注意,大多数窗口都是简单的刷新窗口。这些窗口没有任何离屏位图。渲染到这些窗口的可见区域直接进入屏幕位图。渲染到这些窗口的隐藏区域将被忽略。
因此,大部分渲染都进入单个位图:屏幕位图。
OWB可能主要使用RAM中的像素缓冲区,但没有位图。
您需要编写一些测试程序,在智能刷新窗口中执行一些RectFill()操作(或驱动程序加速的其他函数)。然后多次运行它,并使某些窗口完全或部分隐藏(渲染到智能刷新窗口的可见部分也直接进入屏幕位图。只有渲染到隐藏部分才会进入离屏位图)。Shell(CON:)窗口目前是智能刷新窗口(理论上,如果支持字符映射,它们最好是简单刷新)。图层中的一些东西优化得很差(导致比真正需要的更多来回blitting),尽管如此。也许您指的是带有超级位图的窗口/图层?这些肯定已损坏,但也几乎毫无用处。
BM_OBJ|COLMAP|COLMOD交换是否始终执行真的重要吗?在那个(不需要的)“NoFrameBuffer”出现之前的时代,至少它没有那么重要,因为如果HIDD_Gfx_Show返回与输入相同的位图,则交换实际上不会交换任何东西,因为它放置了与已经存在的值相同的值。它似乎以某种方式很重要。Nouveau是NoFrameBuffer驱动程序,如果我返回接收到的位图,第三次分辨率更改以某种方式导致问题(崩溃或未刷新显示)。我无法追踪原因,只是不进行交换可以使事情正常工作。
是否有人知道为什么来自这些测试的过程没有与我们的HIDD系统集成?特别是现在有了基于GART的nouveau传输,它们提供了相当不错的提升?原因是,如果graphics.hidd位于“ROM”中(这是否属实似乎每隔几年就会改变一次),如果添加了所有转换的真正优化版本,它可能会增加相当大的尺寸。即使补丁rgbconv中的那些确实可以提高速度,它们也不是真正优化的。优化意味着诸如循环展开、尽可能使用SSE或类似技术、使用汇编等。此外,对于目标颜色格式的每个RGB位数多于源颜色格式的情况,人们可能希望有一个选项可以选择快速转换和更准确的转换(例如“快速”:R5G5B5 -> R8G8B8 == RRRRR000GGGGG000BBBBB000。== 像素变暗,因为0填充)== 甚至更多的转换函数并占用空间。通过允许在运行时修补转换函数,还可以更快地编写、编译和检查新例程(patchrgbconv可以选择基准测试并验证例程是否按预期工作)。并且也可以由外部编码人员完成。