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:
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" #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -41,12 +49,6 @@ typedef struct GPUAttachment {
int layer, mip; int layer, mip;
} GPUAttachment; } GPUAttachment;
typedef enum eGPUFrameBufferBits {
GPU_COLOR_BIT = (1 << 0),
GPU_DEPTH_BIT = (1 << 1),
GPU_STENCIL_BIT = (1 << 2),
} eGPUFrameBufferBits;
typedef enum eGPUBackBuffer { typedef enum eGPUBackBuffer {
GPU_BACKBUFFER_LEFT = 0, GPU_BACKBUFFER_LEFT = 0,
GPU_BACKBUFFER_RIGHT, 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.tex) {
if (new_attachment.layer > 0) { if (new_attachment.layer > 0) {
BLI_assert(ELEM(GPU_texture_target(new_attachment.tex), BLI_assert(GPU_texture_cube(new_attachment.tex) || GPU_texture_array(new_attachment.tex));
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_CUBE_MAP,
GL_TEXTURE_CUBE_MAP_ARRAY_ARB));
} }
if (GPU_texture_stencil(new_attachment.tex)) { if (GPU_texture_stencil(new_attachment.tex)) {
BLI_assert(ELEM(type, GPU_FB_DEPTH_STENCIL_ATTACHMENT)); BLI_assert(ELEM(type, GPU_FB_DEPTH_STENCIL_ATTACHMENT));

View File

@@ -115,6 +115,9 @@ class FrameBuffer {
float clear_depth, float clear_depth,
uint clear_stencil) = 0; uint clear_stencil) = 0;
virtual void clear_multi(const float (*clear_col)[4]) = 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, virtual void read(eGPUFrameBufferBits planes,
eGPUDataFormat format, 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(GPU_context_active_get() == context_);
BLI_assert(context_->active_fb == this); BLI_assert(context_->active_fb == this);
@@ -367,17 +369,56 @@ void GLFrameBuffer::clear_multi(const float (*clear_cols)[4])
context_->state_manager->apply_state(); 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 /* WATCH: This can easily access clear_cols out of bounds it clear_cols is not big enough for
* all attachments. * all attachments.
* TODO(fclem) fix this insecurity? */ * TODO(fclem) fix this insecurity? */
int type = GPU_FB_COLOR_ATTACHMENT0; int type = GPU_FB_COLOR_ATTACHMENT0;
for (int i = 0; type < GPU_FB_MAX_ATTACHMENT; i++, type++) { for (int i = 0; type < GPU_FB_MAX_ATTACHMENT; i++, type++) {
if (attachments_[type].tex != NULL) { 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, void GLFrameBuffer::read(eGPUFrameBufferBits plane,

View File

@@ -81,6 +81,9 @@ class GLFrameBuffer : public FrameBuffer {
float clear_depth, float clear_depth,
uint clear_stencil) override; uint clear_stencil) override;
void clear_multi(const float (*clear_cols)[4]) 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, void read(eGPUFrameBufferBits planes,
eGPUDataFormat format, eGPUDataFormat format,