我被告知C和C ++有“未定义的行为”,也就是说,如果我使用“某些结构”,相同的代码在不同的平台上或使用不同的编译器可能会有不同的行为。
这同样适用于OpenCL和/或OpenGL SL吗?
答案 0 :(得分:4)
答案 1 :(得分:3)
是的,根据OpenCL specification 1.1定义前面的未定义行为:
使用OpenCL API调用的行为,内置函数 在内核内部或内核的执行明确没有 由OpenCL定义。不需要符合要求的实现 指定遇到未定义构造时发生的情况 OpenCL的
例如:
CL_MEM_WRITE_ONLY
创建的缓冲区或图像对象中读取”CL_MEM_READ_ONLY
创建的缓冲区或图像对象”clEnqueueReadBuffer
使用缓冲区的其他命令clEnqueueReadBuffer
,同时映射缓冲区有很多方法可以从OpenCL调用未定义的行为。
对于OpenGL SL(specification),有很多容易找到的例子:
const
那么它是编译时错误)#pragma STDGL invariant(all)
]或
函数,然后行为不变的输出集是未定义的“gl_PointSize
或gl_ClipVertex
]会导致未定义的行为”答案 2 :(得分:2)
我被告知C和C ++有“未定义的行为”,也就是说,如果我使用“某些结构”,相同的代码在不同的平台上或使用不同的编译器可能会有不同的行为。
这不是未定义的行为实际意味着什么。这是未定义行为的结果,但这不是它的用途。
规范是关于定义当你做某事时会发生什么。它说什么参数值是好的,哪些是坏的。如果你通过了坏的,它会告诉你你得到了什么错误以及系统的状态。如果当前状态对于您尝试执行的操作无效,则说明会解释您获得的其他类型的错误以及之后对系统状态的意义。
当您使用已定义的行为时,您依赖于您自己与实施之间的合同;该合同称为OpenGL规范。您依靠实现来提供规范所需的有效性检查。而且你依赖于规范所说的实现。如果实现没有正确实现某些东西,那么它就违反了合同。
当规范说某些事情会导致“未定义的行为”时,这意味着做这些事情你正在破坏合同。你不在地图的边缘。您正在做的事情规范没有提供定义的行为;你打破了这笔交易。
换句话说,只要不依赖于未定义的行为,您的代码就会非常便携。这就是它的含义。
通常,如果对其进行测试对实现来说是一个繁重的负担,那么规范就会标记出一些未定义的内容。毕竟,OpenGL确实需要相当快。因此,强迫它测试几乎不可能检查的东西会给驾驶员带来负担,这是他们试图避免的。
然后,有些测试是无法测试的。在OpenGL中,通过将图像绑定为纹理并从中采样,同时将该图像附加到FBO并呈现给它,读取和写入同一图像是非法的。没有办法可以保证测试这种情况。
哦,你可以测试它的大部分。当相同的纹理绑定到FBO和采样器时,您可能无法进行绘制调用。但是,你将无法渲染到相同纹理的不同mipmap;记住:每个mipmap都是一个单独的图像。因此,您可以检查基本/最大级别范围是否允许从绑定到FBO的mipmap进行采样。但是这给用户带来了沉重的负担,因为他们在渲染到不同的mipmap时必须不断调整基本/最大级别。他们使用textureLOD
或类似函数从正确的mipmap中进行采样要容易得多。而且直到运行时才能确定它们是否从该mipmap级别外部进行采样。
OpenCL和OpenGL SL具有未定义的行为,就像许多规范一样。一般来说,由于同样的原因,它是未定义的:测试它会使实现速度慢得令人无法接受,或者测试是不可能的。
答案 3 :(得分:1)
是的,有未定义的行为(你可以通过grep规范找到一些);但要小心,因为这些并不是程序在不同系统上表现不同的唯一方式:并非所有OpenGL实现都是完全可靠的(实际上,大多数都不是)。例如,Nvidia的驱动程序允许在此核心配置文件中调用texture2D
,而这会在其他平台上导致错误(后者是预期的行为)。了解它是否有效的最佳方法是在多个平台(操作系统,GPU和驱动程序)上进行测试。