1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief FBO multisample tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3fFboMultisampleTests.hpp" 25 #include "es3fFboTestCase.hpp" 26 #include "es3fFboTestUtil.hpp" 27 #include "gluTextureUtil.hpp" 28 #include "tcuImageCompare.hpp" 29 #include "tcuTextureUtil.hpp" 30 #include "tcuTestLog.hpp" 31 #include "deStringUtil.hpp" 32 #include "deRandom.hpp" 33 #include "sglrContextUtil.hpp" 34 #include "glwEnums.hpp" 35 36 namespace deqp 37 { 38 namespace gles3 39 { 40 namespace Functional 41 { 42 43 using std::string; 44 using tcu::TestLog; 45 using tcu::Vec2; 46 using tcu::Vec3; 47 using tcu::Vec4; 48 using tcu::IVec2; 49 using tcu::IVec3; 50 using tcu::IVec4; 51 using tcu::UVec4; 52 using namespace FboTestUtil; 53 54 class BasicFboMultisampleCase : public FboTestCase 55 { 56 public: 57 BasicFboMultisampleCase (Context& context, const char* name, const char* desc, deUint32 colorFormat, deUint32 depthStencilFormat, const IVec2& size, int numSamples) 58 : FboTestCase (context, name, desc) 59 , m_colorFormat (colorFormat) 60 , m_depthStencilFormat (depthStencilFormat) 61 , m_size (size) 62 , m_numSamples (numSamples) 63 { 64 } 65 66 protected: 67 void preCheck (void) 68 { 69 checkFormatSupport (m_colorFormat); 70 checkSampleCount (m_colorFormat, m_numSamples); 71 72 if (m_depthStencilFormat != GL_NONE) 73 { 74 checkFormatSupport (m_depthStencilFormat); 75 checkSampleCount (m_depthStencilFormat, m_numSamples); 76 } 77 } 78 79 void render (tcu::Surface& dst) 80 { 81 tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFormat); 82 tcu::TextureFormat depthStencilFmt = m_depthStencilFormat != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFormat) : tcu::TextureFormat(); 83 tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); 84 bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; 85 bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; 86 GradientShader gradShader (getFragmentOutputType(colorFmt)); 87 FlatColorShader flatShader (getFragmentOutputType(colorFmt)); 88 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); 89 deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); 90 deUint32 msaaFbo = 0; 91 deUint32 resolveFbo = 0; 92 deUint32 msaaColorRbo = 0; 93 deUint32 resolveColorRbo = 0; 94 deUint32 msaaDepthStencilRbo = 0; 95 deUint32 resolveDepthStencilRbo = 0; 96 97 // Create framebuffers. 98 for (int ndx = 0; ndx < 2; ndx++) 99 { 100 deUint32& fbo = ndx ? resolveFbo : msaaFbo; 101 deUint32& colorRbo = ndx ? resolveColorRbo : msaaColorRbo; 102 deUint32& depthStencilRbo = ndx ? resolveDepthStencilRbo : msaaDepthStencilRbo; 103 int samples = ndx ? 0 : m_numSamples; 104 105 glGenRenderbuffers(1, &colorRbo); 106 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); 107 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, m_colorFormat, m_size.x(), m_size.y()); 108 109 if (depth || stencil) 110 { 111 glGenRenderbuffers(1, &depthStencilRbo); 112 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo); 113 glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, m_depthStencilFormat, m_size.x(), m_size.y()); 114 } 115 116 glGenFramebuffers(1, &fbo); 117 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 118 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); 119 if (depth) 120 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); 121 if (stencil) 122 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); 123 124 checkError(); 125 checkFramebufferStatus(GL_FRAMEBUFFER); 126 } 127 128 glBindFramebuffer(GL_FRAMEBUFFER, msaaFbo); 129 glViewport(0, 0, m_size.x(), m_size.y()); 130 131 // Clear depth and stencil buffers. 132 glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); 133 134 // Fill MSAA fbo with gradient, depth = [-1..1] 135 glEnable(GL_DEPTH_TEST); 136 gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax); 137 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); 138 139 // Render random-colored quads. 140 { 141 const int numQuads = 8; 142 de::Random rnd (9); 143 144 glDepthFunc(GL_ALWAYS); 145 glEnable(GL_STENCIL_TEST); 146 glStencilFunc(GL_ALWAYS, 0, 0xffu); 147 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); 148 149 for (int ndx = 0; ndx < numQuads; ndx++) 150 { 151 float r = rnd.getFloat(); 152 float g = rnd.getFloat(); 153 float b = rnd.getFloat(); 154 float a = rnd.getFloat(); 155 float x0 = rnd.getFloat(-1.0f, 1.0f); 156 float y0 = rnd.getFloat(-1.0f, 1.0f); 157 float z0 = rnd.getFloat(-1.0f, 1.0f); 158 float x1 = rnd.getFloat(-1.0f, 1.0f); 159 float y1 = rnd.getFloat(-1.0f, 1.0f); 160 float z1 = rnd.getFloat(-1.0f, 1.0f); 161 162 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(r,g,b,a) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin); 163 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(x0, y0, z0), Vec3(x1, y1, z1)); 164 } 165 } 166 167 glDisable(GL_DEPTH_TEST); 168 glDisable(GL_STENCIL_TEST); 169 checkError(); 170 171 // Resolve using glBlitFramebuffer(). 172 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo); 173 glBlitFramebuffer(0, 0, m_size.x(), m_size.y(), 0, 0, m_size.x(), m_size.y(), GL_COLOR_BUFFER_BIT | (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST); 174 175 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFbo); 176 177 if (depth) 178 { 179 // Visualize depth. 180 const int numSteps = 8; 181 const float step = 2.0f / (float)numSteps; 182 183 glEnable(GL_DEPTH_TEST); 184 glDepthFunc(GL_LESS); 185 glDepthMask(GL_FALSE); 186 glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); 187 188 for (int ndx = 0; ndx < numSteps; ndx++) 189 { 190 float d = -1.0f + step*(float)ndx; 191 float c = (float)ndx / (float)(numSteps-1); 192 193 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, c, 1.0f) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin); 194 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, d), Vec3(1.0f, 1.0f, d)); 195 } 196 197 glDisable(GL_DEPTH_TEST); 198 } 199 200 if (stencil) 201 { 202 // Visualize stencil. 203 const int numSteps = 4; 204 const int step = 1; 205 206 glEnable(GL_STENCIL_TEST); 207 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 208 glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); 209 210 for (int ndx = 0; ndx < numSteps; ndx++) 211 { 212 int s = step*ndx; 213 float c = (float)ndx / (float)(numSteps-1); 214 215 glStencilFunc(GL_EQUAL, s, 0xffu); 216 217 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, c, 0.0f, 1.0f) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin); 218 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 219 } 220 221 glDisable(GL_STENCIL_TEST); 222 } 223 224 readPixels(dst, 0, 0, m_size.x(), m_size.y(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); 225 } 226 227 bool colorCompare (const tcu::Surface& reference, const tcu::Surface& result) 228 { 229 const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_colorFormat), tcu::RGBA(12, 12, 12, 12))); 230 231 return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT); 232 } 233 234 bool compare (const tcu::Surface& reference, const tcu::Surface& result) 235 { 236 if (m_depthStencilFormat != GL_NONE) 237 return FboTestCase::compare(reference, result); 238 else 239 return colorCompare(reference, result); 240 } 241 242 private: 243 deUint32 m_colorFormat; 244 deUint32 m_depthStencilFormat; 245 IVec2 m_size; 246 int m_numSamples; 247 }; 248 249 FboMultisampleTests::FboMultisampleTests (Context& context) 250 : TestCaseGroup(context, "msaa", "Multisample FBO tests") 251 { 252 } 253 254 FboMultisampleTests::~FboMultisampleTests (void) 255 { 256 } 257 258 void FboMultisampleTests::init (void) 259 { 260 static const deUint32 colorFormats[] = 261 { 262 // RGBA formats 263 GL_RGBA8, 264 GL_SRGB8_ALPHA8, 265 GL_RGB10_A2, 266 GL_RGBA4, 267 GL_RGB5_A1, 268 269 // RGB formats 270 GL_RGB8, 271 GL_RGB565, 272 273 // RG formats 274 GL_RG8, 275 276 // R formats 277 GL_R8, 278 279 // GL_EXT_color_buffer_float 280 GL_RGBA32F, 281 GL_RGBA16F, 282 GL_R11F_G11F_B10F, 283 GL_RG32F, 284 GL_RG16F, 285 GL_R32F, 286 GL_R16F 287 }; 288 289 static const deUint32 depthStencilFormats[] = 290 { 291 GL_DEPTH_COMPONENT32F, 292 GL_DEPTH_COMPONENT24, 293 GL_DEPTH_COMPONENT16, 294 GL_DEPTH32F_STENCIL8, 295 GL_DEPTH24_STENCIL8, 296 GL_STENCIL_INDEX8 297 }; 298 299 static const int sampleCounts[] = { 2, 4, 8 }; 300 301 for (int sampleCntNdx = 0; sampleCntNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCntNdx++) 302 { 303 int samples = sampleCounts[sampleCntNdx]; 304 tcu::TestCaseGroup* sampleCountGroup = new tcu::TestCaseGroup(m_testCtx, (de::toString(samples) + "_samples").c_str(), ""); 305 addChild(sampleCountGroup); 306 307 // Color formats. 308 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) 309 sampleCountGroup->addChild(new BasicFboMultisampleCase(m_context, getFormatName(colorFormats[fmtNdx]), "", colorFormats[fmtNdx], GL_NONE, IVec2(119, 131), samples)); 310 311 // Depth/stencil formats. 312 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++) 313 sampleCountGroup->addChild(new BasicFboMultisampleCase(m_context, getFormatName(depthStencilFormats[fmtNdx]), "", GL_RGBA8, depthStencilFormats[fmtNdx], IVec2(119, 131), samples)); 314 } 315 } 316 317 } // Functional 318 } // gles3 319 } // deqp 320