Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
glFramebuffer.cpp
Go to the documentation of this file.
1
2
3#include "config.h"
4
6
9
14
16
17namespace Divide
18{
20 : RenderTarget( context, descriptor )
21 , _debugMessage(("Render Target: [ " + name() + " ]").c_str())
22 {
23 gl46core::glCreateFramebuffers( 1, &_framebufferHandle );
24
25 DIVIDE_ASSERT( (_framebufferHandle != 0 && _framebufferHandle != GL_NULL_HANDLE), "glFramebuffer error: Tried to bind an invalid framebuffer!" );
26
27 if constexpr ( Config::ENABLE_GPU_VALIDATION )
28 {
29 // label this FB to be able to tell that it's internally created and nor from a 3rd party lib
30 gl46core::glObjectLabel( gl46core::GL_FRAMEBUFFER,
31 _framebufferHandle,
32 -1,
33 (name() + "_RENDER").c_str());
34 }
35
36 // Everything disabled so that the initial "begin" will override this
37 std::ranges::fill(_previousPolicy._drawMask, false);
38 _attachmentState.resize( GFXDevice::GetDeviceInformation()._maxRTColourAttachments + 1u + 1u ); //colours + depth-stencil
39 }
40
42 {
43 if (!GL_API::DeleteFramebuffers( 1, &_framebufferHandle ))
44 {
46 }
47
49 {
51 {
53 }
54 }
55 }
56
58 {
59 if ( !RenderTarget::initAttachment( att, type, slot ) )
60 {
61 return false;
62 }
63
64 if ( att->_descriptor._externalAttachment == nullptr && Get(att->resolvedTexture())->descriptor()._mipMappingState == MipMappingState::AUTO )
65 {
66 // We do this here to avoid any undefined data if we use this attachment as a texture before we actually draw to it
67 gl46core::glGenerateTextureMipmap( static_cast<glTexture*>(Get(att->resolvedTexture()))->textureHandle() );
68 }
69
70 // Find the appropriate binding point
71 U32 binding = to_U32( gl46core::GL_COLOR_ATTACHMENT0 ) + to_base( slot );
73 {
74 binding = type == RTAttachmentType::DEPTH ? to_U32( gl46core::GL_DEPTH_ATTACHMENT ) : to_U32( gl46core::GL_DEPTH_STENCIL_ATTACHMENT );
75 // Most of these aren't even valid, but hey, doesn't hurt to check
76 _isLayeredDepth = SupportsZOffsetTexture( Get(att->resolvedTexture())->descriptor()._texType );
77 }
78
79 att->binding( binding );
80 _attachmentState[to_base(slot)] = {};
81
82 return true;
83 }
84
85 bool glFramebuffer::toggleAttachment( const U8 attachmentIdx, const AttachmentState state, const U16 levelOffset, const DrawLayerEntry layerOffset, bool layeredRendering )
86 {
88
89 const RTAttachment_uptr& attachment = _attachments[ attachmentIdx ];
90 const Handle<Texture> tex = attachment->renderTexture();
91 if ( tex == INVALID_HANDLE<Texture> )
92 {
93 return false;
94 }
95
96 ResourcePtr<Texture> texPtr = Get(tex);
97
98 if ( texPtr->depth() == 1u )
99 {
100 DIVIDE_ASSERT( layerOffset._layer == 0u );
101 if ( !IsCubeTexture( texPtr->descriptor()._texType ) || layerOffset._cubeFace == 0u )
102 {
103 layeredRendering = true;
104 }
105 }
106
107 const BindingState bState
108 {
109 ._layer = layerOffset,
110 ._levelOffset = levelOffset,
111 ._layeredRendering = layeredRendering,
112 ._attState = state
113 };
114
115 // Compare with old state
116 if ( bState != _attachmentState[attachmentIdx] )
117 {
118 const auto binding = static_cast<gl46core::GLenum>(attachment->binding());
119
120 if ( state == AttachmentState::STATE_DISABLED )
121 {
122 gl46core::glNamedFramebufferTexture( _framebufferHandle, binding, 0u, 0u );
123 if ( _attachmentsAutoResolve[attachmentIdx] )
124 {
125 gl46core::glNamedFramebufferTexture( _framebufferResolveHandle, binding, 0u, 0u );
126 }
127 }
128 else
129 {
130 DIVIDE_ASSERT( bState._layer._layer < texPtr->depth() && bState._levelOffset < texPtr->mipCount());
131
132 ResourcePtr<Texture> resolvedTexPtr = Get( attachment->resolvedTexture() );
133
134 const gl46core::GLuint handle = static_cast<glTexture*>(texPtr)->textureHandle();
135 if ( bState._layer._layer == 0u && bState._layer._cubeFace == 0u && layeredRendering )
136 {
137 gl46core::glNamedFramebufferTexture( _framebufferHandle, binding, handle, bState._levelOffset);
138 if ( _attachmentsAutoResolve[attachmentIdx] )
139 {
140 gl46core::glNamedFramebufferTexture( _framebufferResolveHandle, binding, static_cast<glTexture*>(resolvedTexPtr)->textureHandle(), bState._levelOffset );
141 }
142 }
143 else if ( IsCubeTexture( texPtr->descriptor()._texType ) )
144 {
145 gl46core::glNamedFramebufferTextureLayer( _framebufferHandle, binding, handle, bState._levelOffset, bState._layer._cubeFace + (bState._layer._layer * 6u) );
146 if ( _attachmentsAutoResolve[attachmentIdx] )
147 {
148 gl46core::glNamedFramebufferTextureLayer( _framebufferResolveHandle, binding, static_cast<glTexture*>(resolvedTexPtr)->textureHandle(), bState._levelOffset, bState._layer._cubeFace + (bState._layer._layer * 6u) );
149 }
150 }
151 else
152 {
153 assert(bState._layer._cubeFace == 0u);
154 gl46core::glNamedFramebufferTextureLayer( _framebufferHandle, binding, handle, bState._levelOffset, bState._layer._layer );
155 if ( _attachmentsAutoResolve[attachmentIdx] )
156 {
157 gl46core::glNamedFramebufferTextureLayer( _framebufferResolveHandle, binding, static_cast<glTexture*>(resolvedTexPtr)->textureHandle(), bState._levelOffset, bState._layer._layer );
158 }
159 }
160 }
161
162 _statusCheckQueued = true;
163 _attachmentState[attachmentIdx] = bState;
164 return true;
165 }
166
167 return false;
168 }
169
171 {
172 if ( !RenderTarget::create() )
173 {
174 return false;
175 }
176
177 bool needsAutoResolve = false;
178 for ( U8 i = 0u; i < RT_MAX_ATTACHMENT_COUNT; ++i )
179 {
181 {
182 needsAutoResolve = true;
183 break;
184 }
185 }
186
187 if ( needsAutoResolve && _framebufferResolveHandle == GL_NULL_HANDLE )
188 {
189 gl46core::glCreateFramebuffers( 1, &_framebufferResolveHandle );
190 if constexpr ( Config::ENABLE_GPU_VALIDATION )
191 {
192 gl46core::glObjectLabel( gl46core::GL_FRAMEBUFFER,
194 -1,
195 (name() + "_RESOLVE").c_str() );
196 }
197 }
198 else if ( !needsAutoResolve && _framebufferResolveHandle != GL_NULL_HANDLE )
199 {
201 {
203 }
204
206 }
207
208 for ( U8 i = 0u; i < RT_MAX_ATTACHMENT_COUNT; ++i )
209 {
210 if ( !_attachmentsUsed[i] )
211 {
212 continue;
213 }
214
215 toggleAttachment( i, AttachmentState::STATE_ENABLED, 0u, { ._layer = 0u, ._cubeFace = 0u }, true );
216 }
217
218 // Setup draw buffers
219 prepareBuffers( {} );
220
221 return checkStatus();
222 }
223
224 void glFramebuffer::blitFrom( RenderTarget* source, const RTBlitParams& params )
225 {
227
228 if ( source == nullptr || !IsValid(params) )
229 {
230 return;
231 }
232
233 glFramebuffer* input = static_cast<glFramebuffer*>(source);
234 glFramebuffer* output = this;
235 const vec2<U16> inputDim = input->_descriptor._resolution;
236 const vec2<U16> outputDim = output->_descriptor._resolution;
237
238 gl46core::GLuint inputHandle = input->_framebufferHandle;
240 {
241 inputHandle = input->_framebufferResolveHandle;
242 }
243
244 PROFILE_TAG( "Input_Width", inputDim.width );
245 PROFILE_TAG( "Input_Height", inputDim.height );
246 PROFILE_TAG( "Output_Width", outputDim.width );
247 PROFILE_TAG( "Output_Height",outputDim.height );
248
249 // When reading/writing from/to an FBO, we need to make sure it is complete and doesn't throw a GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS.
250 // An easy way to achieve this is to disable attachments we don't need to write to
251 const auto prepareAttachments = []( glFramebuffer* fbo, const U16 attIndex, const U16 layer, const U16 mip )
252 {
253 bool ret = false;
254 for ( U8 i = 0u; i < RT_MAX_ATTACHMENT_COUNT; ++i )
255 {
256 if ( !fbo->_attachmentsUsed[i] )
257 {
258 continue;
259 }
260
261 if (fbo->toggleAttachment( i, i == attIndex ? AttachmentState::STATE_ENABLED : AttachmentState::STATE_DISABLED, mip, {layer, 0u}, false ) )
262 {
263 ret = true;
264 }
265 }
266
267 return ret;
268 };
269
270 bool readBufferDirty = false;
271
272 for ( const RTBlitEntry entry : params )
273 {
274 if ( entry._input._index == INVALID_INDEX ||
275 entry._output._index == INVALID_INDEX ||
276 !input->_attachmentsUsed[entry._input._index] ||
277 !output->_attachmentsUsed[entry._output._index] )
278 {
279 continue;
280 }
281
282 const RTAttachment_uptr& inAtt = input->_attachments[entry._input._index];
283 const RTAttachment_uptr& outAtt = output->_attachments[entry._output._index];
284 const gl46core::GLenum readBuffer = static_cast<gl46core::GLenum>(inAtt->binding());
285 const gl46core::GLenum writeBuffer = static_cast<gl46core::GLenum>(outAtt->binding());
286
287 const bool isColourBlit = entry._input._index != RT_DEPTH_ATTACHMENT_IDX;
288 if ( isColourBlit )
289 {
290 PROFILE_SCOPE( "Prepare RW Buffers", Profiler::Category::Graphics );
291
292 DIVIDE_ASSERT( entry._output._index != RT_DEPTH_ATTACHMENT_IDX );
293 if ( readBuffer != input->_activeReadBuffer )
294 {
295 input->_activeReadBuffer = readBuffer;
296 gl46core::glNamedFramebufferReadBuffer( inputHandle, readBuffer );
297 readBufferDirty = true;
298 }
299
300 if (output->_colourBuffers._glSlot[0] != writeBuffer)
301 {
302 output->_colourBuffers._glSlot[0] = writeBuffer;
303 output->_colourBuffers._dirty = true;
304 gl46core::glNamedFramebufferDrawBuffers( output->_framebufferHandle,
305 (gl46core::GLsizei)output->_colourBuffers._glSlot.size(),
306 output->_colourBuffers._glSlot.data() );
307 }
308 }
309
310 bool blitted = false, inputDirty = false, outputDirty = false;;
311 U16 layerCount = entry._layerCount;
312 DIVIDE_ASSERT( layerCount != U16_MAX && entry._mipCount != U16_MAX);
313 if ( IsCubeTexture( Get(inAtt->resolvedTexture())->descriptor()._texType ) )
314 {
315 layerCount *= 6u;
316 }
317
318 {
320 for ( U8 layer = 0u; layer < layerCount; ++layer )
321 {
322 PROFILE_TAG("Layer", layer);
323
324 for ( U8 mip = 0u; mip < entry._mipCount; ++mip )
325 {
327 PROFILE_TAG("Mip", mip);
328
329 {
330 PROFILE_SCOPE( "Prepare Attachments Input", Profiler::Category::Graphics );
331 if ( prepareAttachments( input, entry._input._index, entry._input._layerOffset + layer, entry._input._mipOffset + mip ) )
332 {
333 inputDirty = true;
334 }
335 }
336 {
337 PROFILE_SCOPE( "Prepare Attachments Output", Profiler::Category::Graphics );
338 if ( prepareAttachments( output, entry._output._index, entry._output._layerOffset + layer, entry._output._mipOffset + mip ) )
339 {
340 outputDirty = true;
341 }
342 }
343
344 gl46core::glBlitNamedFramebuffer( inputHandle,
345 output->_framebufferHandle,
346 0, 0,
347 inputDim.width, inputDim.height,
348 0, 0,
349 outputDim.width, outputDim.height,
350 isColourBlit ? gl46core::GL_COLOR_BUFFER_BIT : gl46core::GL_DEPTH_BUFFER_BIT,
351 gl46core::GL_NEAREST );
352
354 blitted = true;
355 }
356 }
357 }
358
359 if ( inputDirty )
360 {
361 PROFILE_SCOPE( "Reset Input Attachments", Profiler::Category::Graphics );
362 DIVIDE_ASSERT( input->_attachmentsUsed[entry._input._index] );
363 input->toggleAttachment( entry._input._index, AttachmentState::STATE_ENABLED, 0u, { ._layer = 0u, ._cubeFace = 0u }, true );
364 }
365 if ( outputDirty )
366 {
367 PROFILE_SCOPE( "Reset Output Attachments", Profiler::Category::Graphics );
368 DIVIDE_ASSERT( output->_attachmentsUsed[entry._output._index] );
369 output->toggleAttachment( entry._output._index, AttachmentState::STATE_ENABLED, 0u, { ._layer = 0u, ._cubeFace = 0u }, true );
370 }
371 if ( blitted )
372 {
374 }
375 }
376
377 if ( readBufferDirty )
378 {
379 gl46core::glNamedFramebufferReadBuffer( inputHandle, gl46core::GL_NONE );
380 input->_activeReadBuffer = gl46core::GL_NONE;
381 }
382 }
383
385 {
387
388 bool change = _colourBuffers._dirty;
389 if (!change)
390 {
391 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i)
392 {
393 if ( _previousPolicy._drawMask[i] != drawPolicy._drawMask[i] )
394 {
395 change = true;
396 break;
397 }
398 }
399 }
400
401 if ( change )
402 {
403 bool set = false;
404 // handle colour buffers first
406 for ( U8 j = 0; j < to_base( RTColourAttachmentSlot::COUNT ); ++j )
407 {
408 gl46core::GLenum temp = gl46core::GL_NONE;
409 if ( j < count )
410 {
411 const RTColourAttachmentSlot slot = static_cast<RTColourAttachmentSlot>(j);
412 temp = gl46core::GL_NONE;
413 if ( drawPolicy._drawMask[j] && usesAttachment(RTAttachmentType::COLOUR, slot) )
414 {
415 temp = static_cast<gl46core::GLenum>(getAttachment( RTAttachmentType::COLOUR, slot )->binding());
416 }
417 }
418
419 if ( _colourBuffers._glSlot[j] != temp )
420 {
421 _colourBuffers._glSlot[j] = temp;
422 set = true;
423 }
424 }
425
426 if ( set )
427 {
428 gl46core::glNamedFramebufferDrawBuffers( _framebufferHandle, to_base( RTColourAttachmentSlot::COUNT ), _colourBuffers._glSlot.data() );
429 }
430
431 _colourBuffers._dirty = false;
432 _statusCheckQueued = true;
433 }
434 }
435
436 void glFramebuffer::begin( const RTDrawDescriptor& drawPolicy, const RTClearDescriptor& clearPolicy )
437 {
439
440 DrawLayerEntry targetDepthLayer{};
441
442 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
443 {
444 if ( _attachmentsUsed[i] )
445 {
446 if ( drawPolicy._writeLayers[i]._layer != INVALID_INDEX && (drawPolicy._writeLayers[i]._layer > 0u || drawPolicy._writeLayers[i]._cubeFace > 0u))
447 {
448 targetDepthLayer = drawPolicy._writeLayers[i];
449 break;
450 }
451 }
452 }
453 for ( U8 i = 0u; i < RT_MAX_ATTACHMENT_COUNT; ++i )
454 {
455 if ( _attachmentsUsed[i] )
456 {
457 _previousDrawLayers[i] = drawPolicy._writeLayers[i]._layer == INVALID_INDEX ? targetDepthLayer : drawPolicy._writeLayers[i];
459 }
460 }
461
462 prepareBuffers( drawPolicy );
463
464 if constexpr ( Config::Build::IS_DEBUG_BUILD )
465 {
466 checkStatus();
467 }
468 else
469 {
470 _statusCheckQueued = false;
471 }
472
473 // Set the viewport
475
476 clear( clearPolicy );
477 _previousPolicy = drawPolicy;
478 }
479
481 {
483
484 resolve( mask );
485
486 for ( U8 i = 0u; i < RT_MAX_ATTACHMENT_COUNT; ++i )
487 {
489 }
490
491 }
492
494 {
496 {
497 return;
498 }
499
500 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
501 {
503 {
504 continue;
505 }
506
507 if ( _previousPolicy._drawMask[i] && mask[i] )
508 {
510
511 const gl46core::GLenum rwBuffer = static_cast<gl46core::GLenum>(_attachments[i]->binding());
512 gl46core::glNamedFramebufferReadBuffer( _framebufferHandle, rwBuffer );
513 gl46core::glNamedFramebufferDrawBuffers( _framebufferResolveHandle, 1u, &rwBuffer);
514
515 gl46core::glBlitNamedFramebuffer( _framebufferHandle,
517 0, 0,
519 0, 0,
521 gl46core::GL_COLOR_BUFFER_BIT,
522 gl46core::GL_NEAREST );
523 }
524 }
525
527 {
529
530 gl46core::glBlitNamedFramebuffer( _framebufferHandle,
532 0, 0,
534 0, 0,
536 gl46core::GL_DEPTH_BUFFER_BIT,
537 gl46core::GL_NEAREST );
538 }
539
540
541 gl46core::glNamedFramebufferReadBuffer( _framebufferHandle, gl46core::GL_NONE );
542 _activeReadBuffer = gl46core::GL_NONE;
543 }
544
545 void glFramebuffer::QueueMipMapsRecomputation( const RTAttachment_uptr& attachment )
546 {
548
549 if ( attachment == nullptr )
550 {
551 return;
552 }
553
554 const Handle<Texture> texture = attachment->resolvedTexture();
555 if ( texture != INVALID_HANDLE<Texture> && Get(texture)->descriptor()._mipMappingState == MipMappingState::AUTO )
556 {
557 gl46core::glGenerateTextureMipmap( static_cast<glTexture*>(Get(texture))->textureHandle() );
558 }
559 }
560
561 void glFramebuffer::clear( const RTClearDescriptor& descriptor )
562 {
564 {
565 PROFILE_SCOPE( "Clear Colour Attachments", Profiler::Category::Graphics );
566 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
567 {
568 if ( !_attachmentsUsed[i] || !descriptor[i]._enabled )
569 {
570 continue;
571 }
572
574 DIVIDE_ASSERT( att != nullptr, "glFramebuffer::error: Invalid clear target specified!" );
575
576 const U32 binding = att->binding();
577 if ( static_cast<gl46core::GLenum>(binding) != gl46core::GL_NONE )
578 {
579 const gl46core::GLint buffer = static_cast<gl46core::GLint>(binding - static_cast<gl46core::GLint>(gl46core::GL_COLOR_ATTACHMENT0));
580 const FColour4& colour = descriptor[i]._colour;
581
582 const auto& descriptor = Get( att->renderTexture() )->descriptor();
583 if ( IsNormalizedTexture(descriptor._packing) )
584 {
585 gl46core::glClearNamedFramebufferfv( _framebufferHandle, gl46core::GL_COLOR, buffer, colour._v );
586 }
587 else
588 {
589 switch ( descriptor._dataType )
590 {
593 {
594 gl46core::glClearNamedFramebufferfv( _framebufferHandle, gl46core::GL_COLOR, buffer, colour._v );
595 } break;
596
600 {
601 thread_local vec4<I32> clearColour {
602 FLOAT_TO_CHAR_SNORM( colour.r ),
603 FLOAT_TO_CHAR_SNORM( colour.g ),
604 FLOAT_TO_CHAR_SNORM( colour.b ),
605 FLOAT_TO_CHAR_SNORM( colour.a )
606 };
607
608 gl46core::glClearNamedFramebufferiv( _framebufferHandle, gl46core::GL_COLOR, buffer, clearColour._v );
609 } break;
610
611 default:
612 {
613 thread_local vec4<U32> clearColour {
614 FLOAT_TO_CHAR_UNORM( colour.r ),
615 FLOAT_TO_CHAR_UNORM( colour.g ),
616 FLOAT_TO_CHAR_UNORM( colour.b ),
617 FLOAT_TO_CHAR_UNORM( colour.a )
618 };
619 gl46core::glClearNamedFramebufferuiv( _framebufferHandle, gl46core::GL_COLOR, buffer, clearColour._v );
620 } break;
621 }
622 }
624 }
625 }
626 }
627
629 {
631
633 const FColour4& clearColour = descriptor[RT_DEPTH_ATTACHMENT_IDX]._colour;
635 {
636 gl46core::glClearNamedFramebufferfi( _framebufferHandle, gl46core::GL_DEPTH_STENCIL, 0, clearColour.r, to_I32( clearColour.g) );
637 }
638 else
639 {
640 gl46core::glClearNamedFramebufferfv( _framebufferHandle, gl46core::GL_DEPTH, 0, &clearColour.r );
641 }
643 }
644 }
645
646 bool glFramebuffer::setMipLevelInternal( const U8 attachmentIdx, U16 writeLevel )
647 {
649
650 if ( _attachmentsUsed[attachmentIdx] )
651 {
652 const BindingState& state = _attachmentState[attachmentIdx];
653 return toggleAttachment( attachmentIdx, state._attState, writeLevel, state._layer, state._layeredRendering );
654 }
655
656 return false;
657 }
658
659 void glFramebuffer::setMipLevel( const U16 writeLevel )
660 {
661 if ( writeLevel == U16_MAX )
662 {
663 return;
664 }
665
667
668 bool changedMip = false;
669 bool needsAttachmentDisabled = false;
670
671 changedMip = setMipLevelInternal( RT_DEPTH_ATTACHMENT_IDX, writeLevel ) || changedMip;
672 for ( U8 i = 0u; i < to_base( RTColourAttachmentSlot::COUNT ); ++i )
673 {
674 changedMip = setMipLevelInternal( i, writeLevel ) || changedMip;
675 }
676
677 if ( changedMip && needsAttachmentDisabled )
678 {
679 for ( U8 i = 0u; i < RT_MAX_ATTACHMENT_COUNT; ++i )
680 {
681 const BindingState& state = _attachmentState[i];
682
683 if ( state._levelOffset != writeLevel )
684 {
686 }
687 }
688 }
689 }
690
692 {
693 if ( !_statusCheckQueued )
694 {
695 return true;
696 }
697 _statusCheckQueued = false;
699 {
700 return false;
701 }
702
703 return checkStatusInternal( _framebufferHandle );
704 }
705
706 bool glFramebuffer::checkStatusInternal( const gl46core::GLuint handle )
707 {
708 if constexpr ( Config::ENABLE_GPU_VALIDATION )
709 {
711
712 // check FB status
713 const gl46core::GLenum status = gl46core::glCheckNamedFramebufferStatus( handle, gl46core::GL_FRAMEBUFFER );
714 if ( status == gl46core::GL_FRAMEBUFFER_COMPLETE )
715 {
716 return true;
717 }
718
719 switch ( status )
720 {
721 case gl46core::GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
722 {
723 Console::errorfn( LOCALE_STR( "ERROR_RT_ATTACHMENT_INCOMPLETE" ) );
724 } break;
725 case gl46core::GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
726 {
727 Console::errorfn( LOCALE_STR( "ERROR_RT_NO_IMAGE" ) );
728 } break;
729 case gl46core::GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
730 {
731 Console::errorfn( LOCALE_STR( "ERROR_RT_INCOMPLETE_DRAW_BUFFER" ) );
732 } break;
733 case gl46core::GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
734 {
735 Console::errorfn( LOCALE_STR( "ERROR_RT_INCOMPLETE_READ_BUFFER" ) );
736 } break;
737 case gl46core::GL_FRAMEBUFFER_UNSUPPORTED:
738 {
739 Console::errorfn( LOCALE_STR( "ERROR_RT_UNSUPPORTED" ) );
740 } break;
741 case gl46core::GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
742 {
743 Console::errorfn( LOCALE_STR( "ERROR_RT_INCOMPLETE_MULTISAMPLE" ) );
744 } break;
745 case gl46core::GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
746 {
747 Console::errorfn( LOCALE_STR( "ERROR_RT_INCOMPLETE_LAYER_TARGETS" ) );
748 } break;
749 case gl::GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
750 {
751 Console::errorfn( LOCALE_STR( "ERROR_RT_DIMENSIONS" ) );
752 } break;
753 case gl::GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
754 {
755 Console::errorfn( LOCALE_STR( "ERROR_RT_FORMAT" ) );
756 } break;
757 default:
758 {
759 Console::errorfn( LOCALE_STR( "ERROR_UNKNOWN" ) );
760 } break;
761 }
762
763 DIVIDE_ASSERT( !(*GL_API::GetStateTracker()._assertOnAPIError));
764
765 return false;
766 }
767 else
768 {
769 return true;
770 }
771 }
772
773}; // namespace Divide
#define LOCALE_STR(X)
Definition: Localization.h:91
#define DIVIDE_ASSERT(...)
#define DIVIDE_UNEXPECTED_CALL()
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_TAG(NAME,...)
Definition: Profiler.h:88
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
bool setViewport(const Rect< I32 > &viewport)
Returns true if the viewport was changed.
Definition: GFXDevice.cpp:2051
static const DeviceInformation & GetDeviceInformation() noexcept
Definition: GFXDevice.inl:158
void registerDrawCall() noexcept
Definition: GFXDevice.inl:148
static GLStateTracker & GetStateTracker() noexcept
Definition: GLWrapper.cpp:1749
static bool DeleteFramebuffers(gl46core::GLuint count, gl46core::GLuint *framebuffers)
Definition: GLWrapper.cpp:1908
RTAttachmentDescriptor _descriptor
Definition: RTAttachment.h:128
bool usesAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
RTAttachment * getAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
U16 getWidth() const noexcept
RenderTargetDescriptor _descriptor
Definition: RenderTarget.h:100
virtual bool initAttachment(RTAttachment *att, RTAttachmentType type, RTColourAttachmentSlot slot)
virtual bool create()
Init all attachments. Returns false if already called.
U8 getAttachmentCount(RTAttachmentType type) const noexcept
const Str< 64 > & name() const noexcept
U16 getHeight() const noexcept
RTAttachment_uptr _attachments[RT_MAX_ATTACHMENT_COUNT]
Definition: RenderTarget.h:102
bool _attachmentsAutoResolve[RT_MAX_ATTACHMENT_COUNT]
Definition: RenderTarget.h:104
bool _attachmentsUsed[RT_MAX_ATTACHMENT_COUNT]
Definition: RenderTarget.h:103
bool initAttachment(RTAttachment *att, RTAttachmentType type, RTColourAttachmentSlot slot) override
RTDrawDescriptor _previousPolicy
void blitFrom(RenderTarget *source, const RTBlitParams &params)
void begin(const RTDrawDescriptor &drawPolicy, const RTClearDescriptor &clearPolicy)
eastl::fixed_vector< BindingState, 8+2, true > _attachmentState
gl46core::GLuint _framebufferResolveHandle
glFramebuffer(GFXDevice &context, const RenderTargetDescriptor &descriptor)
bool setMipLevelInternal(U8 attachmentIdx, U16 writeLevel)
void end(const RTTransitionMask &mask)
void prepareBuffers(const RTDrawDescriptor &drawPolicy)
gl46core::GLenum _activeReadBuffer
bool create() override
Bake in all settings and attachments to Prepare it for rendering.
void clear(const RTClearDescriptor &descriptor)
static void QueueMipMapsRecomputation(const RTAttachment_uptr &attachment)
void setMipLevel(U16 writeLevel)
bool toggleAttachment(U8 attachmentIdx, AttachmentState state, U16 levelOffset, DrawLayerEntry layerOffset, bool layeredRendering)
std::array< DrawLayerEntry, RT_MAX_ATTACHMENT_COUNT > _previousDrawLayers
struct Divide::glFramebuffer::ColourBufferState _colourBuffers
void resolve(const RTTransitionMask &mask)
bool checkStatusInternal(gl46core::GLuint handle)
constexpr bool IS_DEBUG_BUILD
Definition: config.h:55
constexpr bool ENABLE_GPU_VALIDATION
Error callbacks, validations, buffer checks, etc. are controlled by this flag. Heavy performance impa...
Definition: config.h:192
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U8 FLOAT_TO_CHAR_UNORM(F32_NORM value) noexcept
Returns round(value * 255)
Definition: MathHelper.inl:307
constexpr U8 INVALID_INDEX
eastl::fixed_vector< RTBlitEntry, MAX_BLIT_ENTRIES, false > RTBlitParams
constexpr I8 FLOAT_TO_CHAR_SNORM(F32_SNORM value) noexcept
Returns clamped value * 128.
Definition: MathHelper.inl:276
constexpr U32 to_U32(const T value)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
Definition: RTAttachment.h:71
bool IsNormalizedTexture(GFXImagePacking packing) noexcept
T * ResourcePtr
Definition: Resource.h:112
uint8_t U8
bool IsCubeTexture(TextureType texType) noexcept
RTAttachmentType
This enum is used when creating render targets to define the channel that the texture will attach to.
Definition: RTAttachment.h:47
bool IsValid(const RTBlitParams &params) noexcept
constexpr gl46core::GLuint GL_NULL_HANDLE
Invalid object value. Used to compare handles and determine if they were properly created.
Definition: glResources.h:105
constexpr U16 U16_MAX
uint16_t U16
RTColourAttachmentSlot
static constexpr U8 RT_MAX_ATTACHMENT_COUNT
Definition: RTAttachment.h:72
std::array< RTClearEntry, RT_MAX_ATTACHMENT_COUNT > RTClearDescriptor
bool[RT_MAX_ATTACHMENT_COUNT] RTTransitionMask
constexpr I32 to_I32(const T value)
FORCE_INLINE T * Get(const Handle< T > handle)
uint32_t U32
Project const SceneEntry & entry
Definition: DefaultScene.h:41
bool SupportsZOffsetTexture(TextureType texType) noexcept
constexpr auto to_base(const Type value) -> Type
static NO_INLINE void errorfn(const char *format, T &&... args)
U8 _cubeFace
Ignored for non cube textures.
U16 _layer
bool setDepthWrite(bool state)
RTAttachment * _externalAttachment
Definition: RTAttachment.h:65
DrawLayerEntry _writeLayers[RT_MAX_ATTACHMENT_COUNT]
bool _layeredRendering
Set to true to bind all image layers to the render target (e.g. for Geometry Shader layered rendering...
std::array< gl46core::GLenum, to_base(RTColourAttachmentSlot::COUNT)> _glSlot