]> git.sesse.net Git - casparcg/blob - core/mixer/gpu/fence.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / mixer / gpu / fence.cpp
1 #include "../../StdAfx.h"\r
2 \r
3 #include "fence.h"\r
4 \r
5 #include "ogl_device.h"\r
6 \r
7 #include <common/gl/gl_check.h>\r
8 \r
9 #include <gl/glew.h>\r
10 \r
11 namespace caspar { namespace core {\r
12 \r
13 struct fence::implementation\r
14 {\r
15         GLsync sync_;\r
16 \r
17         implementation() : sync_(0){}\r
18         ~implementation(){glDeleteSync(sync_);}\r
19                 \r
20         void set()\r
21         {\r
22                 glDeleteSync(sync_);\r
23                 sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\r
24         }\r
25 \r
26         bool ready() const\r
27         {\r
28                 if(!sync_)\r
29                         return true;\r
30 \r
31                 GLsizei length = 0;\r
32                 int values[] = {0};\r
33 \r
34                 GL(glGetSynciv(sync_, GL_SYNC_STATUS, 1, &length, values));\r
35 \r
36                 return values[0] == GL_SIGNALED;\r
37         }\r
38 \r
39         void wait(ogl_device& ogl)\r
40         {       \r
41                 int delay = 0;\r
42                 if(!ogl.invoke([this]{return ready();}, high_priority))\r
43                 {\r
44                         while(!ogl.invoke([this]{return ready();}, normal_priority) && delay < 20)\r
45                         {\r
46                                 delay += 2;\r
47                                 Sleep(2);\r
48                         }\r
49                 }\r
50                 \r
51                 static tbb::atomic<size_t> count;\r
52                 static tbb::atomic<bool> warned;\r
53                 \r
54                 if(delay > 2 && ++count > 16)\r
55                 {\r
56                         if(!warned.fetch_and_store(true))\r
57                         {\r
58                                 CASPAR_LOG(warning) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms. Further warnings are sent to trace log level."\r
59                                                                         << L" You can ignore this warning if you do not notice any problems with output video. This warning is caused by insufficent support or performance of your graphics card for OpenGL based memory transfers. "\r
60                                                                         << L" Please try to update your graphics drivers or update your graphics card, see recommendations on (www.casparcg.com)."\r
61                                                                         << L" Further help is available at (www.casparcg.com/forum).";\r
62                         }\r
63                         else\r
64                                 CASPAR_LOG(trace) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms.";\r
65                 }\r
66         }\r
67 };\r
68         \r
69 fence::fence() \r
70 {\r
71         static bool log_flag = false;\r
72 \r
73         if(GLEW_ARB_sync)\r
74                 impl_.reset(new implementation());\r
75         else if(!log_flag)\r
76         {\r
77                 CASPAR_LOG(warning) << "[fence] GL_SYNC not supported, running without fences. This might cause performance degradation when running multiple channels and short buffer depth.";\r
78                 log_flag = true;\r
79         }\r
80 }\r
81 \r
82 void fence::set() \r
83 {\r
84         if(impl_)\r
85                 impl_->set();\r
86 }\r
87 \r
88 bool fence::ready() const \r
89 {\r
90         return impl_ ? impl_->ready() : true;\r
91 }\r
92 \r
93 void fence::wait(ogl_device& ogl)\r
94 {\r
95         if(impl_)\r
96                 impl_->wait(ogl);\r
97 }\r
98 \r
99 }}