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.
This commit is contained in:
Clément Foucault 2020-09-03 21:52:30 +02:00
parent 22a84a673a
commit db21c12abe
5 changed files with 60 additions and 14 deletions

View File

@ -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,

View File

@ -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));

View File

@ -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,

View File

@ -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,

View File

@ -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,