From db21c12abedd7606a3aaf50f70e506a24d9f0e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 3 Sep 2020 21:52:30 +0200 Subject: GPUFramebuffer: Encapsulate single attachement clear This is in preparation of using it to clear single texture. Also includes minor cleanups about not using tex target in assert and adding enum operators. --- source/blender/gpu/GPU_framebuffer.h | 14 ++++--- source/blender/gpu/intern/gpu_framebuffer.cc | 5 +-- .../blender/gpu/intern/gpu_framebuffer_private.hh | 3 ++ source/blender/gpu/opengl/gl_framebuffer.cc | 49 ++++++++++++++++++++-- source/blender/gpu/opengl/gl_framebuffer.hh | 3 ++ 5 files changed, 60 insertions(+), 14 deletions(-) diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index aca7156fa5b..f4599ac44bb 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -32,6 +32,14 @@ #include "GPU_texture.h" +typedef enum eGPUFrameBufferBits { + GPU_COLOR_BIT = (1 << 0), + GPU_DEPTH_BIT = (1 << 1), + GPU_STENCIL_BIT = (1 << 2), +} eGPUFrameBufferBits; + +ENUM_OPERATORS(eGPUFrameBufferBits) + #ifdef __cplusplus extern "C" { #endif @@ -41,12 +49,6 @@ typedef struct GPUAttachment { int layer, mip; } GPUAttachment; -typedef enum eGPUFrameBufferBits { - GPU_COLOR_BIT = (1 << 0), - GPU_DEPTH_BIT = (1 << 1), - GPU_STENCIL_BIT = (1 << 2), -} eGPUFrameBufferBits; - typedef enum eGPUBackBuffer { GPU_BACKBUFFER_LEFT = 0, GPU_BACKBUFFER_RIGHT, diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index bb17ee8edf4..742fdc6d8b3 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -96,10 +96,7 @@ void FrameBuffer::attachment_set(GPUAttachmentType type, const GPUAttachment &ne if (new_attachment.tex) { if (new_attachment.layer > 0) { - BLI_assert(ELEM(GPU_texture_target(new_attachment.tex), - GL_TEXTURE_2D_ARRAY, - GL_TEXTURE_CUBE_MAP, - GL_TEXTURE_CUBE_MAP_ARRAY_ARB)); + BLI_assert(GPU_texture_cube(new_attachment.tex) || GPU_texture_array(new_attachment.tex)); } if (GPU_texture_stencil(new_attachment.tex)) { BLI_assert(ELEM(type, GPU_FB_DEPTH_STENCIL_ATTACHMENT)); diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 0f442ff2b34..58ee841c076 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -115,6 +115,9 @@ class FrameBuffer { float clear_depth, uint clear_stencil) = 0; virtual void clear_multi(const float (*clear_col)[4]) = 0; + virtual void clear_attachment(GPUAttachmentType type, + eGPUDataFormat data_format, + const void *clear_value) = 0; virtual void read(eGPUFrameBufferBits planes, eGPUDataFormat format, diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc index 133d56a075d..4be471b236a 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.cc +++ b/source/blender/gpu/opengl/gl_framebuffer.cc @@ -356,7 +356,9 @@ void GLFrameBuffer::clear(eGPUFrameBufferBits buffers, } } -void GLFrameBuffer::clear_multi(const float (*clear_cols)[4]) +void GLFrameBuffer::clear_attachment(GPUAttachmentType type, + eGPUDataFormat data_format, + const void *clear_value) { BLI_assert(GPU_context_active_get() == context_); BLI_assert(context_->active_fb == this); @@ -367,17 +369,56 @@ void GLFrameBuffer::clear_multi(const float (*clear_cols)[4]) context_->state_manager->apply_state(); + if (type == GPU_FB_DEPTH_STENCIL_ATTACHMENT) { + BLI_assert(data_format == GPU_DATA_UNSIGNED_INT_24_8); + float depth = ((*(uint32_t *)clear_value) & 0x00FFFFFFu) / (float)0x00FFFFFFu; + int stencil = ((*(uint32_t *)clear_value) >> 24); + glClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil); + } + else if (type == GPU_FB_DEPTH_ATTACHMENT) { + if (data_format == GPU_DATA_FLOAT) { + glClearBufferfv(GL_DEPTH, 0, (GLfloat *)clear_value); + } + else if (data_format == GPU_DATA_UNSIGNED_INT) { + float depth = *(uint32_t *)clear_value / (float)0xFFFFFFFFu; + glClearBufferfv(GL_DEPTH, 0, &depth); + } + else { + BLI_assert(!"Unhandled data format"); + } + } + else { + int slot = type - GPU_FB_COLOR_ATTACHMENT0; + switch (data_format) { + case GPU_DATA_FLOAT: + glClearBufferfv(GL_COLOR, slot, (GLfloat *)clear_value); + break; + case GPU_DATA_UNSIGNED_INT: + glClearBufferuiv(GL_COLOR, slot, (GLuint *)clear_value); + break; + case GPU_DATA_INT: + glClearBufferiv(GL_COLOR, slot, (GLint *)clear_value); + break; + default: + BLI_assert(!"Unhandled data format"); + break; + } + } + + GPU_write_mask(write_mask); +} + +void GLFrameBuffer::clear_multi(const float (*clear_cols)[4]) +{ /* WATCH: This can easily access clear_cols out of bounds it clear_cols is not big enough for * all attachments. * TODO(fclem) fix this insecurity? */ int type = GPU_FB_COLOR_ATTACHMENT0; for (int i = 0; type < GPU_FB_MAX_ATTACHMENT; i++, type++) { if (attachments_[type].tex != NULL) { - glClearBufferfv(GL_COLOR, i, clear_cols[i]); + this->clear_attachment(GPU_FB_COLOR_ATTACHMENT0 + i, GPU_DATA_FLOAT, clear_cols[i]); } } - - GPU_write_mask(write_mask); } void GLFrameBuffer::read(eGPUFrameBufferBits plane, diff --git a/source/blender/gpu/opengl/gl_framebuffer.hh b/source/blender/gpu/opengl/gl_framebuffer.hh index 8d386116159..8173d3b2416 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.hh +++ b/source/blender/gpu/opengl/gl_framebuffer.hh @@ -81,6 +81,9 @@ class GLFrameBuffer : public FrameBuffer { float clear_depth, uint clear_stencil) override; void clear_multi(const float (*clear_cols)[4]) override; + void clear_attachment(GPUAttachmentType type, + eGPUDataFormat data_format, + const void *clear_value) override; void read(eGPUFrameBufferBits planes, eGPUDataFormat format, -- cgit v1.2.3