BsGLRenderTexture.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsGLRenderTexture.h"
  4. #include "BsGLPixelFormat.h"
  5. #include "BsGLPixelBuffer.h"
  6. #include "BsTextureView.h"
  7. namespace bs
  8. {
  9. #define PROBE_SIZE 16
  10. static const GLenum depthFormats[] =
  11. {
  12. GL_NONE,
  13. GL_DEPTH_COMPONENT16,
  14. GL_DEPTH_COMPONENT32,
  15. GL_DEPTH24_STENCIL8,
  16. GL_DEPTH32F_STENCIL8
  17. };
  18. #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum))
  19. GLRenderTextureCore::GLRenderTextureCore(const RENDER_TEXTURE_DESC_CORE& desc, UINT32 deviceIdx)
  20. :RenderTextureCore(desc, deviceIdx), mProperties(desc, true), mFB(nullptr)
  21. {
  22. assert(deviceIdx == 0 && "Multiple GPUs not supported natively on OpenGL.");
  23. }
  24. GLRenderTextureCore::~GLRenderTextureCore()
  25. {
  26. if (mFB != nullptr)
  27. bs_delete(mFB);
  28. }
  29. void GLRenderTextureCore::initialize()
  30. {
  31. RenderTextureCore::initialize();
  32. if (mFB != nullptr)
  33. bs_delete(mFB);
  34. mFB = bs_new<GLFrameBufferObject>();
  35. for (size_t i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  36. {
  37. if (mColorSurfaces[i] != nullptr)
  38. {
  39. GLTextureCore* glColorSurface = static_cast<GLTextureCore*>(mColorSurfaces[i]->getTexture().get());
  40. GLSurfaceDesc surfaceDesc;
  41. surfaceDesc.numSamples = getProperties().getMultisampleCount();
  42. if (mColorSurfaces[i]->getNumArraySlices() == 1) // Binding a single texture layer
  43. {
  44. surfaceDesc.allLayers = glColorSurface->getProperties().getNumFaces() == 1;
  45. if (glColorSurface->getProperties().getTextureType() != TEX_TYPE_3D)
  46. {
  47. surfaceDesc.zoffset = 0;
  48. surfaceDesc.buffer = glColorSurface->getBuffer(mColorSurfaces[i]->getFirstArraySlice(),
  49. mColorSurfaces[i]->getMostDetailedMip());
  50. }
  51. else
  52. {
  53. surfaceDesc.zoffset = mColorSurfaces[i]->getFirstArraySlice();
  54. surfaceDesc.buffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
  55. }
  56. }
  57. else // Binding an array of textures or a range of 3D texture slices
  58. {
  59. surfaceDesc.allLayers = true;
  60. if (glColorSurface->getProperties().getTextureType() != TEX_TYPE_3D)
  61. {
  62. if (mColorSurfaces[i]->getNumArraySlices() != glColorSurface->getProperties().getNumFaces())
  63. LOGWRN("OpenGL doesn't support binding of arbitrary ranges for array textures. The entire range will be bound instead.");
  64. surfaceDesc.zoffset = 0;
  65. surfaceDesc.buffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
  66. }
  67. else
  68. {
  69. if (mColorSurfaces[i]->getNumArraySlices() != glColorSurface->getProperties().getDepth())
  70. LOGWRN("OpenGL doesn't support binding of arbitrary ranges for array textures. The entire range will be bound instead.");
  71. surfaceDesc.zoffset = 0;
  72. surfaceDesc.buffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
  73. }
  74. }
  75. mFB->bindSurface((UINT32)i, surfaceDesc);
  76. }
  77. else
  78. {
  79. mFB->unbindSurface((UINT32)i);
  80. }
  81. }
  82. if (mDepthStencilSurface != nullptr && mDepthStencilSurface->getTexture() != nullptr)
  83. {
  84. GLTextureCore* glDepthStencilTexture = static_cast<GLTextureCore*>(mDepthStencilSurface->getTexture().get());
  85. SPtr<GLPixelBuffer> depthStencilBuffer = nullptr;
  86. if (glDepthStencilTexture->getProperties().getTextureType() != TEX_TYPE_3D)
  87. {
  88. depthStencilBuffer = glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(),
  89. mDepthStencilSurface->getMostDetailedMip());
  90. }
  91. mFB->bindDepthStencil(depthStencilBuffer);
  92. }
  93. }
  94. void GLRenderTextureCore::getCustomAttribute(const String& name, void* data) const
  95. {
  96. if(name=="FBO")
  97. {
  98. *static_cast<GLFrameBufferObject**>(data) = mFB;
  99. }
  100. else if (name == "GL_FBOID" || name == "GL_MULTISAMPLEFBOID")
  101. {
  102. *static_cast<GLuint*>(data) = mFB->getGLFBOID();
  103. }
  104. }
  105. GLRTTManager::GLRTTManager()
  106. :mBlitReadFBO(0), mBlitWriteFBO(0)
  107. {
  108. detectFBOFormats();
  109. glGenFramebuffers(1, &mBlitReadFBO);
  110. glGenFramebuffers(1, &mBlitWriteFBO);
  111. }
  112. GLRTTManager::~GLRTTManager()
  113. {
  114. glDeleteFramebuffers(1, &mBlitReadFBO);
  115. glDeleteFramebuffers(1, &mBlitWriteFBO);
  116. }
  117. bool GLRTTManager::_tryFormat(GLenum depthFormat, GLenum stencilFormat)
  118. {
  119. GLuint status, depthRB = 0, stencilRB = 0;
  120. bool failed = false;
  121. if(depthFormat != GL_NONE)
  122. {
  123. // Generate depth renderbuffer
  124. glGenRenderbuffers(1, &depthRB);
  125. // Bind it to FBO
  126. glBindRenderbuffer(GL_RENDERBUFFER, depthRB);
  127. // Allocate storage for depth buffer
  128. glRenderbufferStorage(GL_RENDERBUFFER, depthFormat,
  129. PROBE_SIZE, PROBE_SIZE);
  130. // Attach depth
  131. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  132. GL_RENDERBUFFER, depthRB);
  133. }
  134. if(stencilFormat != GL_NONE)
  135. {
  136. // Generate stencil renderbuffer
  137. glGenRenderbuffers(1, &stencilRB);
  138. // Bind it to FBO
  139. glBindRenderbuffer(GL_RENDERBUFFER, stencilRB);
  140. glGetError();
  141. // Allocate storage for stencil buffer
  142. glRenderbufferStorage(GL_RENDERBUFFER, stencilFormat,
  143. PROBE_SIZE, PROBE_SIZE);
  144. if(glGetError() != GL_NO_ERROR)
  145. failed = true;
  146. // Attach stencil
  147. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
  148. GL_RENDERBUFFER, stencilRB);
  149. if(glGetError() != GL_NO_ERROR)
  150. failed = true;
  151. }
  152. status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  153. // Detach and destroy
  154. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  155. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
  156. if (depthRB)
  157. glDeleteRenderbuffers(1, &depthRB);
  158. if (stencilRB)
  159. glDeleteRenderbuffers(1, &stencilRB);
  160. return status == GL_FRAMEBUFFER_COMPLETE && !failed;
  161. }
  162. bool GLRTTManager::_tryPackedFormat(GLenum packedFormat)
  163. {
  164. GLuint packedRB = 0;
  165. bool failed = false; // flag on GL errors
  166. // Generate renderbuffer
  167. glGenRenderbuffers(1, &packedRB);
  168. // Bind it to FBO
  169. glBindRenderbuffer(GL_RENDERBUFFER, packedRB);
  170. // Allocate storage for buffer
  171. glRenderbufferStorage(GL_RENDERBUFFER, packedFormat, PROBE_SIZE, PROBE_SIZE);
  172. glGetError();
  173. // Attach depth
  174. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  175. GL_RENDERBUFFER, packedRB);
  176. if(glGetError() != GL_NO_ERROR)
  177. failed = true;
  178. // Attach stencil
  179. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
  180. GL_RENDERBUFFER, packedRB);
  181. if(glGetError() != GL_NO_ERROR)
  182. failed = true;
  183. GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  184. // Detach and destroy
  185. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  186. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
  187. glDeleteRenderbuffers(1, &packedRB);
  188. return status == GL_FRAMEBUFFER_COMPLETE && !failed;
  189. }
  190. void GLRTTManager::detectFBOFormats()
  191. {
  192. // Try all formats, and report which ones work as target
  193. GLuint fb = 0, tid = 0;
  194. GLint old_drawbuffer = 0, old_readbuffer = 0;
  195. GLenum target = GL_TEXTURE_2D;
  196. glGetIntegerv (GL_DRAW_BUFFER, &old_drawbuffer);
  197. glGetIntegerv (GL_READ_BUFFER, &old_readbuffer);
  198. for(size_t x=0; x<PF_COUNT; ++x)
  199. {
  200. mProps[x].valid = false;
  201. // Fetch GL format token
  202. GLenum fmt = GLPixelUtil::getGLInternalFormat((PixelFormat)x);
  203. if(fmt == GL_NONE && x!=0)
  204. continue;
  205. // No test for compressed formats
  206. if(PixelUtil::isCompressed((PixelFormat)x))
  207. continue;
  208. // Create and attach framebuffer
  209. glGenFramebuffers(1, &fb);
  210. glBindFramebuffer(GL_FRAMEBUFFER, fb);
  211. if (fmt!=GL_NONE && !PixelUtil::isDepth((PixelFormat)x))
  212. {
  213. // Create and attach texture
  214. glGenTextures(1, &tid);
  215. glBindTexture(target, tid);
  216. // Set some default parameters so it won't fail on NVidia cards
  217. if (GLEW_VERSION_1_2)
  218. glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
  219. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  220. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  221. glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  222. glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  223. glTexImage2D(target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
  224. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tid, 0);
  225. }
  226. else
  227. {
  228. // Draw to nowhere -- stencil/depth only
  229. glDrawBuffer(GL_NONE);
  230. glReadBuffer(GL_NONE);
  231. }
  232. // Check status
  233. GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  234. // Ignore status in case of fmt==GL_NONE, because no implementation will accept
  235. // a buffer without *any* attachment. Buffers with only stencil and depth attachment
  236. // might still be supported, so we must continue probing.
  237. if(fmt == GL_NONE || status == GL_FRAMEBUFFER_COMPLETE)
  238. {
  239. mProps[x].valid = true;
  240. // For each depth/stencil formats
  241. for (UINT32 depth = 0; depth < DEPTHFORMAT_COUNT; ++depth)
  242. {
  243. if (depthFormats[depth] != GL_DEPTH24_STENCIL8 && depthFormats[depth] != GL_DEPTH32F_STENCIL8)
  244. {
  245. if (_tryFormat(depthFormats[depth], GL_NONE))
  246. {
  247. /// Add mode to allowed modes
  248. FormatProperties::Mode mode;
  249. mode.depth = depth;
  250. mode.stencil = 0;
  251. mProps[x].modes.push_back(mode);
  252. }
  253. }
  254. else
  255. {
  256. // Packed depth/stencil format
  257. if (_tryPackedFormat(depthFormats[depth]))
  258. {
  259. /// Add mode to allowed modes
  260. FormatProperties::Mode mode;
  261. mode.depth = depth;
  262. mode.stencil = 0; // unuse
  263. mProps[x].modes.push_back(mode);
  264. }
  265. }
  266. }
  267. }
  268. // Delete texture and framebuffer
  269. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  270. glDeleteFramebuffers(1, &fb);
  271. glFinish();
  272. if (fmt != GL_NONE)
  273. glDeleteTextures(1, &tid);
  274. }
  275. // It seems a bug in nVidia driver: glBindFramebuffer should restore
  276. // draw and read buffers, but in some unclear circumstances it won't.
  277. glDrawBuffer(old_drawbuffer);
  278. glReadBuffer(old_readbuffer);
  279. String fmtstring = "";
  280. for(size_t x = 0; x < PF_COUNT; ++x)
  281. {
  282. if(mProps[x].valid)
  283. fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" ";
  284. }
  285. }
  286. PixelFormat GLRTTManager::getSupportedAlternative(PixelFormat format)
  287. {
  288. if(checkFormat(format))
  289. return format;
  290. // Find first alternative
  291. PixelComponentType pct = PixelUtil::getElementType(format);
  292. switch(pct)
  293. {
  294. case PCT_BYTE: format = PF_A8R8G8B8; break;
  295. case PCT_FLOAT16: format = PF_FLOAT16_RGBA; break;
  296. case PCT_FLOAT32: format = PF_FLOAT32_RGBA; break;
  297. default: break;
  298. }
  299. if(checkFormat(format))
  300. return format;
  301. // If none at all, return to default
  302. return PF_A8R8G8B8;
  303. }
  304. GLRenderTexture::GLRenderTexture(const RENDER_TEXTURE_DESC& desc)
  305. :RenderTexture(desc), mProperties(desc, true)
  306. {
  307. }
  308. }