OpenCL中的深度缓冲

OpenCL中的深度缓冲,opencl,Opencl,我想在OpenCL中进行一些自定义渲染。我需要一个深度缓冲区。我一直在搜索,但由于编译器优化,许多解决方案不再有效 下面是绘制点的基本内核。如果两个点在同一位置,我只想画一个更靠近相机的点 \uuuuuu内核无效渲染点(\uuuu全局常量uint4*点,\uuuu全局浮点*zbuffer,\uuuu全局uint*img) { int i=获取全局id(0); uint4点=点[i]; int pos=点y*宽度+点x; 如果(点z

我想在
OpenCL
中进行一些自定义渲染。我需要一个深度缓冲区。我一直在搜索,但由于编译器优化,许多解决方案不再有效

下面是绘制点的基本内核。如果两个点在同一位置,我只想画一个更靠近相机的点

\uuuuuu内核无效渲染点(\uuuu全局常量uint4*点,\uuuu全局浮点*zbuffer,\uuuu全局uint*img)
{
int i=获取全局id(0);
uint4点=点[i];
int pos=点y*宽度+点x;
如果(点z
但是,这种简单的方法不起作用,因为由于并行性和缓冲写回,zbuffer不会立即为所有线程更新

我正在使用OpenCL1.2,包括32位原子扩展

问题:
如何实现深度缓冲?

我怀疑问题不在于并行性和原子性,而在于一种不利的数据类型

深度缓冲区应为浮点格式,可以是
float
(32位)或
half
(16位)。在3D到2D转换算法中,生成的x和y位置应为
int
short
uchar
将分辨率限制为256x256),而生成的z位置应为浮点。这样,当两个点的z位置相似时,比如说
3.4
3.2
,仍然可以正确绘制更接近的点,而如果使用整数数据类型,则两个点的深度都将为
3
,最后绘制的点将指示像素颜色

同样对于
img
缓冲区,我建议使用数据类型
uint
,以便使用完整的32位颜色

除了数据类型之外,算法的其余部分也可以工作。下面是我对OpenCL方法的实现,它绘制一个像素并检查z缓冲区。出于性能原因,我对z缓冲区使用数据类型
half

void uuu属性uuu((始终为内联))绘制(常量整数x、常量整数y、常量浮点z、常量整数颜色、全局整数*位图、全局半*zbuffer){
如果(x=2*def_sceen_w | | y=2*def_sceen_h)返回;//如果点在屏幕外,则取消绘图
常数int index=y*2*def\u sceen\u w+x;

如果(z我怀疑问题不是并行性和原子性,而是一种不利的数据类型

深度缓冲区应为浮点格式,可以是
float
(32位)或
half
(16位)。在3D到2D转换算法中,生成的x和y位置应为
int
short
uchar
将分辨率限制为256x256)而产生的z位置应该是浮点。这样,当两个点的z位置相似时,比如说
3.4
3.2
,可以正确绘制更接近的z位置,而如果使用整数数据类型,则两个点的深度都将为
3
,最后绘制的z位置将指示像素的坐标洛尔

同样对于
img
缓冲区,我建议使用数据类型
uint
,以便使用完整的32位颜色

除了数据类型之外,算法的其余部分也可以工作。下面是我对OpenCL方法的实现,该方法绘制一个像素并检查z缓冲区。出于性能原因,我对z缓冲区使用数据类型
half

void uuu属性uuu((始终为内联))绘制(常量整数x、常量整数y、常量浮点z、常量整数颜色、全局整数*位图、全局半*zbuffer){
如果(x=2*def_sceen_w | | y=2*def_sceen_h)返回;//如果点在屏幕外,则取消绘图
常数int index=y*2*def\u sceen\u w+x;
如果(z一个很长的注释:

用户函数不支持原子性

对于单个整数值,有一个原子_min函数,它将两个值(1在目标地址中,1在参数中)中的较小值写入目标地址:

如果将浮点型深度值乘以1000或1000000,则可以使用此基于整数的函数将像素值钳制在最接近的多边形后面。但原子在全局访问上速度较慢。如果每个像素没有被许多多边形访问,则速度可能不会太慢。但仍然会有对主内存的无序访问,而ch对gpu内存控制器不好,因为每次访问多个数据的概率很低。要部分解决这一问题,您可以对opencl工作项进行排序(根据线程id和z索引(不是zbuffer,而是屏幕2D位置))以便“可能”编译器或硬件“连接”(如果可能,不知道)多个并行(和独立、相邻的1、2、3、4)原子一起读/写

但是,由于您希望切换两个32位值,而不仅仅是深度,因此应使用64位整数(64位原子仅在OpenCL 2.0+上),其最重要的部分是深度(使原子最小),而另一半(img)是自动切换的。为此,您需要“64位原子”:

只要将该值的前一半(最重要的一半)作为深度,它就应该始终在深度上执行“min”操作,但对于完全相同的两个深度值,它还将使用“img”进行切换值。当两个z值完全相同时,这将导致zbuffer上的一个红色、蓝色或绿色值始终位于顶部。如果尚未使用深度偏移,至少这可以解决闪烁问题

如果在同一个像素后面有数千个多边形,原子学的速度可能会非常慢。最好的情况是每个多边形(或它渲染的任何点)1个像素,并且只使用工作索引的z顺序变换。按深度排序img应该使其“稳定”无论场景拓扑如何,都可以看到相同性能的算法

但是,如果你以某种方式将屏幕分成256个正方形,并给每个正方形加上s
int atomic_min (volatile __local int *p ,   int val)
long atom_min (volatile __local long *p, long val)