Bug Summary

File:Source/Core/VideoBackends/OGL/Src/PerfQuery.cpp
Location:line 84, column 44
Description:Division by zero

Annotated Source Code

1#include "RenderBase.h"
2#include "GLUtil.h"
3#include "PerfQuery.h"
4
5namespace OGL
6{
7
8PerfQuery::PerfQuery()
9 : m_query_read_pos()
10 , m_query_count()
11{
12 for (u32 i = 0; i != ArraySize(m_query_buffer)ArraySizeImpl<decltype(m_query_buffer)>::value; ++i)
13 glGenQueries__glewGenQueries(1, &m_query_buffer[i].query_id);
14
15 ResetQuery();
16}
17
18PerfQuery::~PerfQuery()
19{
20 for (u32 i = 0; i != ArraySize(m_query_buffer)ArraySizeImpl<decltype(m_query_buffer)>::value; ++i)
21 glDeleteQueries__glewDeleteQueries(1, &m_query_buffer[i].query_id);
22}
23
24void PerfQuery::EnableQuery(PerfQueryGroup type)
25{
26 if (!ShouldEmulate())
1
Taking false branch
27 return;
28
29 // Is this sane?
30 if (m_query_count > ArraySize(m_query_buffer)ArraySizeImpl<decltype(m_query_buffer)>::value / 2)
2
Taking true branch
31 WeakFlush();
32
33 if (ArraySize(m_query_buffer)ArraySizeImpl<decltype(m_query_buffer)>::value == m_query_count)
3
Taking true branch
34 {
35 FlushOne();
4
Calling 'PerfQuery::FlushOne'
36 //ERROR_LOG(VIDEO, "Flushed query buffer early!");
37 }
38
39 // start query
40 if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
41 {
42 auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ArraySize(m_query_buffer)ArraySizeImpl<decltype(m_query_buffer)>::value];
43
44 glBeginQuery__glewBeginQuery(GL_SAMPLES_PASSED0x8914, entry.query_id);
45 entry.query_type = type;
46
47 ++m_query_count;
48 }
49}
50
51void PerfQuery::DisableQuery(PerfQueryGroup type)
52{
53 if (!ShouldEmulate())
54 return;
55
56 // stop query
57 if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
58 {
59 glEndQuery__glewEndQuery(GL_SAMPLES_PASSED0x8914);
60 }
61}
62
63bool PerfQuery::IsFlushed() const
64{
65 if (!ShouldEmulate())
66 return true;
67
68 return 0 == m_query_count;
69}
70
71void PerfQuery::FlushOne()
72{
73 if (!ShouldEmulate())
5
Taking false branch
74 return;
75
76 auto& entry = m_query_buffer[m_query_read_pos];
77
78 GLuint result = 0;
79 glGetQueryObjectuiv__glewGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT0x8866, &result);
80
81 // NOTE: Reported pixel metrics should be referenced to native resolution
82 m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight();
83
84 m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer)ArraySizeImpl<decltype(m_query_buffer)>::value;
6
Division by zero
85 --m_query_count;
86}
87
88// TODO: could selectively flush things, but I don't think that will do much
89void PerfQuery::FlushResults()
90{
91 if (!ShouldEmulate())
92 return;
93
94 while (!IsFlushed())
95 FlushOne();
96}
97
98void PerfQuery::WeakFlush()
99{
100 if (!ShouldEmulate())
101 return;
102
103 while (!IsFlushed())
104 {
105 auto& entry = m_query_buffer[m_query_read_pos];
106
107 GLuint result = GL_FALSE0;
108 glGetQueryObjectuiv__glewGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE0x8867, &result);
109
110 if (GL_TRUE1 == result)
111 {
112 FlushOne();
113 }
114 else
115 {
116 break;
117 }
118 }
119}
120
121void PerfQuery::ResetQuery()
122{
123 m_query_count = 0;
124 std::fill_n(m_results, ArraySize(m_results)ArraySizeImpl<decltype(m_results)>::value, 0);
125}
126
127u32 PerfQuery::GetQueryResult(PerfQueryType type)
128{
129 if (!ShouldEmulate())
130 return 0;
131
132 u32 result = 0;
133
134 if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
135 {
136 result = m_results[PQG_ZCOMP_ZCOMPLOC];
137 }
138 else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
139 {
140 result = m_results[PQG_ZCOMP];
141 }
142 else if (type == PQ_BLEND_INPUT)
143 {
144 result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
145 }
146 else if (type == PQ_EFB_COPY_CLOCKS)
147 {
148 result = m_results[PQG_EFB_COPY_CLOCKS];
149 }
150
151 return result / 4;
152}
153
154} // namespace