在工作中,我们开发了两种产品,它们都具有OpenGL 3.x +和GLES 2.0/3.0 +后端.团队是独立的,但确实有一些重叠,我们最近讨论的表现glGetError.
在这两种产品中,设计都是这样的,没有GL调用应该生成记录的错误代码glGetError.为了检测这样的错误,在调试中我们有一个宏,它glGetError在每个GL调用之后添加一个,并且如果检测到任何错误它会断言,因为这意味着存在错误.在我的产品上,默认情况下启用此功能,另一方面,必须明确启用它.
这些已存在于我工作多年的产品的代码库中,我们发现它们会导致性能下降,通常在许多平台上都会达到25%左右.我们已经确定这是一个合理的价格,以便及早发现错误.另一个团队在某些情况下声称,添加这些检查可能会使其产品在60FPS下的执行速度降至<1FPS,从而使产品无法使用,这就是默认情况下不启用它们的原因.这两款产品均可在许多OpenGL/GLES平台(PC,OSX,Linux,iOS和Android)上运行.
我理解glGetError降低性能背后的原因; 您(可能)需要CPU/GPU同步才能使上一个操作的状态正确.根据我的理解,这应该将预期的帧时间从" MAX(CPU time, GPU time)"(假设没有其他同步点,没有排队的帧)更改为" CPU time + GPU time + synchronization overheap"(假设每个 glGetError调用产生一个同步点).这是不正确的推理,还是有使用性能降低的其他原因glGetError?
我一直认为glGetError调试中的每次调用是合理的事情(至少在没有错误的GL调用之后).是不是这种情况还是不被视为"最佳做法"?是否存在一些可能导致极端性能问题的情况,例如其他团队描述的问题(例如,使用特定的GL调用和/或平台)?
在福尔康,你可以使用vkCreateGraphicsPipeline或vkCreateComputePipeline创建管道衍生物,具有basePipelineHandle或basePipelineIndex成员VkGraphicsPipelineCreateInfo/ VkComputePipelineCreateInfo.文档声明此功能可用于性能原因:
衍生管道的目标是使用父项作为起点创建它们更便宜,并且在同一父项的子项之间切换/绑定更有效(在主机或设备上).
这为我提出了很多问题:
VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT.始终使用此标志是否存在缺点(例如,如果您将来可能从此创建派生管道)?我为这个竞争性编程问题写了一个解决方案.它通过了所有测试用例,除了最后一个案例关闭了一个,我无法弄清楚原因.这个问题可以这样说:假设一个群体中每个人有多少便士,有多少钱可以转手,这样群体中的每个人都会在财富中彼此相差一分钱?
我的程序很简单.我修改它只是操作一个每个人有多少便士的数组:
def transfer(A):
A.sort(key = lambda x:-x)
extra = sum(A) % len(A)
average = sum(A) // len(A)
high = sum([abs(x - (average+1)) for x in A[:extra]])
low = sum([abs(x - average) for x in A[extra:]])
return (high+low)/2
Run Code Online (Sandbox Code Playgroud)
它失败的测试用例如下:
print(transfer([613, 944, 7845, 8908, 12312, 22378, 27877, 54757, 55476, 90707, 91289, 178189]))
Run Code Online (Sandbox Code Playgroud)
我的代码说答案是240710,而"正确"的答案是240709.我的虫子在哪里?
vkGetInstanceProcAddr并且vkGetDeviceProcAddr在API文档中完全遗漏了.但是,他们需要使用交换链执行命令(从而制作任何有意义的Vulkan应用程序).此外,SDK附带的cube/tri演示使用它们非常不一致.
这两种方法是否可以互换,如果没有,有什么区别?
在Vulkan附带的API-Samples中,似乎在调用vkWaitForFences之后总是vkQueueSubmit直接或通过execute_queue_command_buffer(在util_init.hpp中)调用.调用vkWaitForFences将阻止CPU执行,直到GPU完成之前的所有工作vkQueueSubmit.这实际上不允许同时构造多个帧,这(理论上)显着地限制了性能.
是否需要这些调用,如果是这样,是否有另一种方法在构造新帧之前不要求GPU空闲?
对于资源转换,您需要知道资源的"之前"和"之后" VkImageLayout(例如,VkImageMemoryBarrier传递给vkCmdPipelineBarrier).Vulkan不保证任何命令缓冲区的执行顺序,除非在API文档中明确说明(从这个答案).但是,vkCmdPipelineBarrier明确地说它在调用之前和之后在命令缓冲区中创建命令之间的依赖关系.因此,当在单个命令缓冲区内转换图像时,可以在任何时刻"知道"图像的布局.
但是,vkQueueSumbit不强制执行命令缓冲区的执行顺序.如果有两个命令缓冲区,每个命令缓冲区都vkCmdPipelineBarrier调用将相同的图像转换为不同的布局,那么这两个操作之间是否存在依赖关系,还是在这种情况下需要显式同步?
编译器供应商已经采用零碎的C++ 11功能,这是可预测的,因为其中许多功能都不易实现.
报告编译器完全支持的规范的标准方法是通过__cplusplus预定义的宏.但是,主要供应商报告__cplusplus= 199711L,这意味着他们只是完全支持C++ 98(例如MSVC14).这(大概)意味着它们并不完全支持C++ 11规范,即使它们可能实现了大部分功能.
我想开始使用C++ 11功能,当它们可用时(并且当它们不可用时回退到现有代码).但是,我的代码必须支持许多编译器,包括我可能无法使用的专有编译器.是否有任何标准方法可以知道编译器可以使用哪些C++ 11功能,而不知道具体使用哪个编译器?(如果编译器以非标准方式运行,则检测行为可能不正确).
注意:这个问题是我的问题" static_assert c ++ 11的可用性 "的概括,这个问题并不是很受欢迎,因为我觉得我的动机被误解了.
根据Khronos OpenGL ES Registry,GLES 3.0的扩展头实际上是<GLES2/gl2ext.h>.gl3ext.h应为空,仅提供旧版兼容性.因此,如果要包含GLES 3.0标头,则应该:
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
Run Code Online (Sandbox Code Playgroud)
但是,使用Android NDK进行编译时,看起来gl2ext.h内部的那个版本会出现#include <GLES2/gl2.h>以下错误*(我正在使用API-19进行编译):
C:\android-ndk-r10e\platforms\android-19\arch-arm\usr\include\GLES2\gl2ext.h(6): includes this header:
C:\android-ndk-r10e\platforms\android-19\arch-arm\usr\include\GLES2\gl2.h(572,37): error : conflicting types for 'glShaderSource'
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
^
C:\android-ndk-r10e\platforms\android-19\arch-arm\usr\include\GLES3\gl3.h(905,39): note: previous declaration is here
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
Run Code Online (Sandbox Code Playgroud)
这是因为原型glShaderSource从GLES 2.0改为GLES 3.0核心.这是glext标头的Android NDK版本中的错误,还是我没有做正确的事情?
我正在尝试将多个补丁从一个 git 存储库应用到另一个。我已经创建了补丁(我想要 13 个最新更改):
cd repoA
git format-patch -13 -o ..\patch-directory
cd ..\repoB
git am ..\patch-directory\*.patch
Run Code Online (Sandbox Code Playgroud)
这给出:
fatal: could not open '..\patch-directory\*.patch' for reading: Invalid argument
Run Code Online (Sandbox Code Playgroud)
一个非常相似的问题,似乎表明这是正确的方法(如何一次应用多个 git 补丁),但它不起作用。我可以通过在多个命令中传递完整文件名来单独应用补丁(并且,我可以轻松创建一个脚本来逐一应用它们),但是,我想知道为什么这不起作用。
我在用git version 2.9.2.windows.1。
我试图想出一个我前一个问题的答案(自动确定用户定义的函数是否等效于隐式函数).我的想法是我会编译进出复制构造函数,然后反汇编代码,并检查它们是否相同.代码:
struct A
{
int B;
A() : B(0) { }
#ifdef COPY_CONSTRUCTOR
A(const A& a) : B(a.B) { }
#endif
};
#include <stdio.h>
int main()
{
A a;
A b(a);
printf("%d", b.B);
}
Run Code Online (Sandbox Code Playgroud)
编译(cygwin gcc v4.9.3):
gcc -o a1.exe main.cpp -std=c++11 -g -O0 -DCOPY_CONSTRUCTOR
gcc -o a2.exe main.cpp -std=c++11 -g -O0 -fno-elide-constructors
Run Code Online (Sandbox Code Playgroud)
然后转储反汇编构造函数的反汇编(_ZN1AC1ERKS_是A的复制构造函数的错位名称):
gdb -batch -ex 'file a1.exe' -ex 'disass _ZN1AC1ERKS_'
Run Code Online (Sandbox Code Playgroud)
生产:
Dump of assembler code for function A::A(A const&):
0x0000000100401770 <+0>: push %rbp
0x0000000100401771 …Run Code Online (Sandbox Code Playgroud) c++ ×8
vulkan ×4
opengl-es ×2
algorithm ×1
android ×1
android-ndk ×1
c++11 ×1
debugging ×1
g++ ×1
git ×1
onlinejudge ×1
opengl ×1
patch ×1
performance ×1
python ×1
python-3.x ×1