]> git.sesse.net Git - casparcg/blob - core/mixer/gpu/fence.cpp
Merge pull request #136 from cambell-prince/master_chroma
[casparcg] / core / mixer / gpu / fence.cpp
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "../../StdAfx.h"\r
23 \r
24 #include "fence.h"\r
25 \r
26 #include "ogl_device.h"\r
27 \r
28 #include <common/gl/gl_check.h>\r
29 \r
30 #include <gl/glew.h>\r
31 \r
32 namespace caspar { namespace core {\r
33 \r
34 struct fence::implementation\r
35 {\r
36         GLsync sync_;\r
37 \r
38         implementation() : sync_(0){}\r
39         ~implementation(){glDeleteSync(sync_);}\r
40                 \r
41         void set()\r
42         {\r
43                 glDeleteSync(sync_);\r
44                 sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\r
45         }\r
46 \r
47         bool ready() const\r
48         {\r
49                 if(!sync_)\r
50                         return true;\r
51 \r
52                 GLsizei length = 0;\r
53                 int values[] = {0};\r
54 \r
55                 GL(glGetSynciv(sync_, GL_SYNC_STATUS, 1, &length, values));\r
56 \r
57                 return values[0] == GL_SIGNALED;\r
58         }\r
59 \r
60         void wait(ogl_device& ogl)\r
61         {       \r
62                 int delay = 0;\r
63                 if(!ogl.invoke([this]{return ready();}, high_priority))\r
64                 {\r
65                         while(!ogl.invoke([this]{return ready();}, normal_priority) && delay < 20)\r
66                         {\r
67                                 delay += 2;\r
68                                 Sleep(2);\r
69                         }\r
70                 }\r
71                 \r
72                 static tbb::atomic<size_t> count;\r
73                 static tbb::atomic<bool> warned;\r
74                 \r
75                 if(delay > 2 && ++count > 50)\r
76                 {\r
77                         if(!warned.fetch_and_store(true))\r
78                         {\r
79                                 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
80                                                                         << 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
81                                                                         << L" Please try to update your graphics drivers or update your graphics card, see recommendations on (www.casparcg.com)."\r
82                                                                         << L" Further help is available at (www.casparcg.com/forum).";\r
83                         }\r
84                         else\r
85                                 CASPAR_LOG(trace) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms.";\r
86                 }\r
87         }\r
88 };\r
89         \r
90 fence::fence() \r
91 {\r
92         static bool log_flag = false;\r
93 \r
94         if(GLEW_ARB_sync)\r
95                 impl_.reset(new implementation());\r
96         else if(!log_flag)\r
97         {\r
98                 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
99                 log_flag = true;\r
100         }\r
101 }\r
102 \r
103 void fence::set() \r
104 {\r
105         if(impl_)\r
106                 impl_->set();\r
107 }\r
108 \r
109 bool fence::ready() const \r
110 {\r
111         return impl_ ? impl_->ready() : true;\r
112 }\r
113 \r
114 void fence::wait(ogl_device& ogl)\r
115 {\r
116         if(impl_)\r
117                 impl_->wait(ogl);\r
118 }\r
119 \r
120 }}