Compare commits
25 Commits
temp-editm
...
tmp-gltext
Author | SHA1 | Date | |
---|---|---|---|
784da45955 | |||
263ee86fb4 | |||
![]() |
d1479c437b | ||
![]() |
0038b598cf | ||
![]() |
efd00731f5 | ||
![]() |
219e263b59 | ||
![]() |
5265ed7be2 | ||
5b314f884d | |||
af095ab71f | |||
6f998edf2a | |||
bd081711d6 | |||
42e5de3f4d | |||
fd4f766d58 | |||
922abf37b2 | |||
cfba534403 | |||
1394c0b852 | |||
![]() |
84cb571c1f | ||
![]() |
34921b47f7 | ||
5f7cc8cf51 | |||
ffa351d533 | |||
e58408cbaf | |||
19d056cb85 | |||
da306fb2fc | |||
63b6e87d98 | |||
f7e1c007ab |
@@ -34,8 +34,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "glew-mx.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable : 4251 4275)
|
# pragma warning(disable : 4251 4275)
|
||||||
@@ -99,7 +97,6 @@ struct OCIO_GLSLShader {
|
|||||||
/** Uniform locations. */
|
/** Uniform locations. */
|
||||||
GLint dither_loc;
|
GLint dither_loc;
|
||||||
GLint overlay_loc;
|
GLint overlay_loc;
|
||||||
GLint overlay_tex_loc;
|
|
||||||
GLint predivide_loc;
|
GLint predivide_loc;
|
||||||
GLint curve_mapping_loc;
|
GLint curve_mapping_loc;
|
||||||
GLint ubo_bind;
|
GLint ubo_bind;
|
||||||
@@ -110,9 +107,10 @@ struct OCIO_GLSLShader {
|
|||||||
struct OCIO_GLSLLut3d {
|
struct OCIO_GLSLLut3d {
|
||||||
/** Cache IDs */
|
/** Cache IDs */
|
||||||
std::string cacheId;
|
std::string cacheId;
|
||||||
/** OpenGL Texture handles. 0 if not allocated. */
|
/** OpenGL Texture handles. NULL if not allocated. */
|
||||||
GLuint texture;
|
GPUTexture *texture;
|
||||||
GLuint texture_display;
|
GPUTexture *texture_display;
|
||||||
|
GPUTexture *texture_dummy;
|
||||||
/** Error checking. */
|
/** Error checking. */
|
||||||
bool valid;
|
bool valid;
|
||||||
};
|
};
|
||||||
@@ -123,7 +121,7 @@ struct OCIO_GLSLCurveMappping {
|
|||||||
/** GPU Uniform Buffer handle. 0 if not allocated. */
|
/** GPU Uniform Buffer handle. 0 if not allocated. */
|
||||||
GPUUniformBuf *buffer;
|
GPUUniformBuf *buffer;
|
||||||
/** OpenGL Texture handles. 0 if not allocated. */
|
/** OpenGL Texture handles. 0 if not allocated. */
|
||||||
GLuint texture;
|
GPUTexture *texture;
|
||||||
/** Error checking. */
|
/** Error checking. */
|
||||||
bool valid;
|
bool valid;
|
||||||
};
|
};
|
||||||
@@ -186,11 +184,10 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
__func__);
|
"OCIOShader");
|
||||||
|
|
||||||
if (shader->shader) {
|
if (shader->shader) {
|
||||||
shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither");
|
shader->dither_loc = GPU_shader_get_uniform(shader->shader, "dither");
|
||||||
shader->overlay_tex_loc = GPU_shader_get_uniform(shader->shader, "overlay_texture");
|
|
||||||
shader->overlay_loc = GPU_shader_get_uniform(shader->shader, "overlay");
|
shader->overlay_loc = GPU_shader_get_uniform(shader->shader, "overlay");
|
||||||
shader->predivide_loc = GPU_shader_get_uniform(shader->shader, "predivide");
|
shader->predivide_loc = GPU_shader_get_uniform(shader->shader, "predivide");
|
||||||
shader->curve_mapping_loc = GPU_shader_get_uniform(shader->shader, "curve_mapping");
|
shader->curve_mapping_loc = GPU_shader_get_uniform(shader->shader, "curve_mapping");
|
||||||
@@ -202,6 +199,7 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
|
|||||||
/* Set texture bind point uniform once. This is saved by the shader. */
|
/* Set texture bind point uniform once. This is saved by the shader. */
|
||||||
GPUShader *sh = shader->shader;
|
GPUShader *sh = shader->shader;
|
||||||
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), 0);
|
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), 0);
|
||||||
|
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), 1);
|
||||||
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_texture"), 2);
|
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_texture"), 2);
|
||||||
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_display_texture"), 3);
|
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "lut3d_display_texture"), 3);
|
||||||
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), 4);
|
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), 4);
|
||||||
@@ -258,24 +256,13 @@ static void updateGLSLLut3d(OCIO_GLSLLut3d *lut3d,
|
|||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
ConstProcessorRcPtr *processor = ocio_processors[i];
|
ConstProcessorRcPtr *processor = ocio_processors[i];
|
||||||
GLuint texture = (&lut3d->texture)[i];
|
GPUTexture *texture = (&lut3d->texture)[i];
|
||||||
|
|
||||||
(*processor)->getGpuLut3D(lut_data, *shader_desc);
|
(*processor)->getGpuLut3D(lut_data, *shader_desc);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
int offset[3] = {0, 0, 0};
|
||||||
glBindTexture(GL_TEXTURE_3D, texture);
|
int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
|
||||||
|
GPU_texture_update_sub(texture, GPU_DATA_FLOAT, lut_data, UNPACK3(offset), UNPACK3(extent));
|
||||||
glTexSubImage3D(GL_TEXTURE_3D,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LUT3D_EDGE_SIZE,
|
|
||||||
LUT3D_EDGE_SIZE,
|
|
||||||
LUT3D_EDGE_SIZE,
|
|
||||||
GL_RGB,
|
|
||||||
GL_FLOAT,
|
|
||||||
lut_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_freeN(lut_data);
|
MEM_freeN(lut_data);
|
||||||
@@ -295,41 +282,31 @@ static void ensureGLSLLut3d(OCIO_GLSLLut3d **lut3d_ptr,
|
|||||||
|
|
||||||
OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d);
|
OCIO_GLSLLut3d *lut3d = OBJECT_GUARDED_NEW(OCIO_GLSLLut3d);
|
||||||
|
|
||||||
glGenTextures(3, &lut3d->texture);
|
int extent[3] = {LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE};
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
lut3d->texture = GPU_texture_create_3d("OCIOLut", UNPACK3(extent), 1, GPU_RGB16F, NULL);
|
||||||
GLuint texture = (&lut3d->texture)[i];
|
GPU_texture_filter_mode(lut3d->texture, true);
|
||||||
|
GPU_texture_wrap_mode(lut3d->texture, false, true);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
lut3d->texture_display = GPU_texture_create_3d(
|
||||||
glBindTexture(GL_TEXTURE_3D, texture);
|
"OCIOLutDisplay", UNPACK3(extent), 1, GPU_RGB16F, NULL);
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
GPU_texture_filter_mode(lut3d->texture_display, true);
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
GPU_texture_wrap_mode(lut3d->texture_display, false, true);
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glTexImage3D(GL_TEXTURE_3D,
|
lut3d->texture_dummy = GPU_texture_create_error(2, false);
|
||||||
0,
|
|
||||||
GL_RGB16F,
|
|
||||||
LUT3D_EDGE_SIZE,
|
|
||||||
LUT3D_EDGE_SIZE,
|
|
||||||
LUT3D_EDGE_SIZE,
|
|
||||||
0,
|
|
||||||
GL_RGB,
|
|
||||||
GL_FLOAT,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id);
|
updateGLSLLut3d(lut3d, processor_scene_to_ui, processpr_ui_to_display, shaderDesc, cache_id);
|
||||||
|
|
||||||
lut3d->valid = (lut3d->texture != 0);
|
lut3d->valid = (lut3d->texture && lut3d->texture_display);
|
||||||
|
|
||||||
*lut3d_ptr = lut3d;
|
*lut3d_ptr = lut3d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
|
static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &lut3d->texture);
|
GPU_texture_free(lut3d->texture);
|
||||||
|
GPU_texture_free(lut3d->texture_display);
|
||||||
|
GPU_texture_free(lut3d->texture_dummy);
|
||||||
|
|
||||||
OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d);
|
OBJECT_GUARDED_DELETE(lut3d, OCIO_GLSLLut3d);
|
||||||
}
|
}
|
||||||
@@ -342,19 +319,11 @@ static void freeGLSLLut3d(OCIO_GLSLLut3d *lut3d)
|
|||||||
static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap,
|
static void allocateCurveMappingTexture(OCIO_GLSLCurveMappping *curvemap,
|
||||||
OCIO_CurveMappingSettings *curve_mapping_settings)
|
OCIO_CurveMappingSettings *curve_mapping_settings)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &curvemap->texture);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
glBindTexture(GL_TEXTURE_1D, curvemap->texture);
|
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
/* Do not initialize. Only if used. */
|
|
||||||
int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1;
|
int lut_size = curve_mapping_settings ? curve_mapping_settings->lut_size : 1;
|
||||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16F, lut_size, 0, GL_RGBA, GL_FLOAT, NULL);
|
/* Do not initialize. Only if used. */
|
||||||
|
curvemap->texture = GPU_texture_create_1d("OCIOCurveMap", lut_size, 1, GPU_RGBA16F, NULL);
|
||||||
|
GPU_texture_filter_mode(curvemap->texture, false);
|
||||||
|
GPU_texture_wrap_mode(curvemap->texture, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */
|
/* curve_mapping_settings can be null. In this case we alloc a dummy curvemap. */
|
||||||
@@ -381,7 +350,7 @@ static void ensureGLSLCurveMapping(OCIO_GLSLCurveMappping **curvemap_ptr,
|
|||||||
|
|
||||||
static void freeGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap)
|
static void freeGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &curvemap->texture);
|
GPU_texture_free(curvemap->texture);
|
||||||
GPU_uniformbuf_free(curvemap->buffer);
|
GPU_uniformbuf_free(curvemap->buffer);
|
||||||
|
|
||||||
OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping);
|
OBJECT_GUARDED_DELETE(curvemap, OCIO_GLSLCurveMappping);
|
||||||
@@ -400,20 +369,16 @@ static void updateGLSLCurveMapping(OCIO_GLSLCurveMappping *curvemap,
|
|||||||
|
|
||||||
if (curvemap->cacheId == 0) {
|
if (curvemap->cacheId == 0) {
|
||||||
/* This cache was previously used as dummy. Recreate the texture. */
|
/* This cache was previously used as dummy. Recreate the texture. */
|
||||||
glDeleteTextures(1, &curvemap->texture);
|
GPU_texture_free(curvemap->texture);
|
||||||
allocateCurveMappingTexture(curvemap, curve_mapping_settings);
|
allocateCurveMappingTexture(curvemap, curve_mapping_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update texture. */
|
/* Update texture. */
|
||||||
glActiveTexture(GL_TEXTURE2);
|
int offset[3] = {0, 0, 0};
|
||||||
glBindTexture(GL_TEXTURE_1D, curvemap->texture);
|
int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
|
||||||
glTexSubImage1D(GL_TEXTURE_1D,
|
const float *pixels = curve_mapping_settings->lut;
|
||||||
0,
|
GPU_texture_update_sub(
|
||||||
0,
|
curvemap->texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent));
|
||||||
curve_mapping_settings->lut_size,
|
|
||||||
GL_RGBA,
|
|
||||||
GL_FLOAT,
|
|
||||||
curve_mapping_settings->lut);
|
|
||||||
|
|
||||||
/* Update uniforms. */
|
/* Update uniforms. */
|
||||||
OCIO_GLSLCurveMappingParameters data;
|
OCIO_GLSLCurveMappingParameters data;
|
||||||
@@ -581,16 +546,13 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r,
|
|||||||
/* Bind textures to sampler units. Texture 0 is set by caller.
|
/* Bind textures to sampler units. Texture 0 is set by caller.
|
||||||
* Uniforms have already been set for texture bind points.*/
|
* Uniforms have already been set for texture bind points.*/
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
if (!use_overlay) {
|
||||||
glBindTexture(GL_TEXTURE_3D, shader_lut->texture);
|
/* Avoid missing binds. */
|
||||||
|
GPU_texture_bind(shader_lut->texture_dummy, 1);
|
||||||
glActiveTexture(GL_TEXTURE3);
|
}
|
||||||
glBindTexture(GL_TEXTURE_3D, shader_lut->texture_display);
|
GPU_texture_bind(shader_lut->texture, 2);
|
||||||
|
GPU_texture_bind(shader_lut->texture_display, 3);
|
||||||
glActiveTexture(GL_TEXTURE4);
|
GPU_texture_bind(shader_curvemap->texture, 4);
|
||||||
glBindTexture(GL_TEXTURE_1D, shader_curvemap->texture);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
/* Bind UBO. */
|
/* Bind UBO. */
|
||||||
GPU_uniformbuf_bind(shader_curvemap->buffer, shader->ubo_bind);
|
GPU_uniformbuf_bind(shader_curvemap->buffer, shader->ubo_bind);
|
||||||
@@ -599,12 +561,11 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r,
|
|||||||
immBindShader(shader->shader);
|
immBindShader(shader->shader);
|
||||||
|
|
||||||
/* Bind Shader and set uniforms. */
|
/* Bind Shader and set uniforms. */
|
||||||
// glUseProgram(shader->program);
|
// GPU_shader_bind(shader->shader);
|
||||||
glUniform1f(shader->dither_loc, dither);
|
GPU_shader_uniform_float(shader->shader, shader->dither_loc, dither);
|
||||||
glUniform1i(shader->overlay_tex_loc, use_overlay ? 1 : 0);
|
GPU_shader_uniform_int(shader->shader, shader->overlay_loc, use_overlay);
|
||||||
glUniform1i(shader->overlay_loc, use_overlay);
|
GPU_shader_uniform_int(shader->shader, shader->predivide_loc, use_predivide);
|
||||||
glUniform1i(shader->predivide_loc, use_predivide);
|
GPU_shader_uniform_int(shader->shader, shader->curve_mapping_loc, use_curve_mapping);
|
||||||
glUniform1i(shader->curve_mapping_loc, use_curve_mapping);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -187,8 +187,6 @@ static GPUTexture *blf_batch_cache_texture_load(void)
|
|||||||
int offset_x = bitmap_len_landed % tex_width;
|
int offset_x = bitmap_len_landed % tex_width;
|
||||||
int offset_y = bitmap_len_landed / tex_width;
|
int offset_y = bitmap_len_landed / tex_width;
|
||||||
|
|
||||||
GPU_texture_bind(gc->texture, 0);
|
|
||||||
|
|
||||||
/* TODO(germano): Update more than one row in a single call. */
|
/* TODO(germano): Update more than one row in a single call. */
|
||||||
while (remain) {
|
while (remain) {
|
||||||
int remain_row = tex_width - offset_x;
|
int remain_row = tex_width - offset_x;
|
||||||
@@ -229,16 +227,17 @@ void blf_batch_draw(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPUTexture *texture = blf_batch_cache_texture_load();
|
GPUTexture *texture = blf_batch_cache_texture_load();
|
||||||
GPU_texture_bind(texture, 0);
|
|
||||||
GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len);
|
GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len);
|
||||||
GPU_vertbuf_use(g_batch.verts); /* send data */
|
GPU_vertbuf_use(g_batch.verts); /* send data */
|
||||||
|
|
||||||
GPU_batch_program_set_builtin(g_batch.batch, GPU_SHADER_TEXT);
|
GPU_batch_program_set_builtin(g_batch.batch, GPU_SHADER_TEXT);
|
||||||
GPU_batch_uniform_1i(g_batch.batch, "glyph", 0);
|
GPU_batch_texture_bind(g_batch.batch, "glyph", texture);
|
||||||
GPU_batch_draw(g_batch.batch);
|
GPU_batch_draw(g_batch.batch);
|
||||||
|
|
||||||
GPU_blend(GPU_BLEND_NONE);
|
GPU_blend(GPU_BLEND_NONE);
|
||||||
|
|
||||||
|
GPU_texture_unbind(texture);
|
||||||
|
|
||||||
/* restart to 1st vertex data pointers */
|
/* restart to 1st vertex data pointers */
|
||||||
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
|
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
|
||||||
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
|
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
|
||||||
|
@@ -508,8 +508,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
|
|||||||
if (gc->texture) {
|
if (gc->texture) {
|
||||||
GPU_texture_free(gc->texture);
|
GPU_texture_free(gc->texture);
|
||||||
}
|
}
|
||||||
gc->texture = GPU_texture_create_nD(
|
gc->texture = GPU_texture_create_1d_array(__func__, w, h, 1, GPU_R8, NULL);
|
||||||
w, h, 0, 1, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, NULL);
|
|
||||||
|
|
||||||
gc->bitmap_len_landed = 0;
|
gc->bitmap_len_landed = 0;
|
||||||
}
|
}
|
||||||
|
@@ -95,7 +95,7 @@ static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multivi
|
|||||||
tile_info[3] = tile->runtime.tilearray_size[1] / array_h;
|
tile_info[3] = tile->runtime.tilearray_size[1] / array_h;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_1d_array(width, 2, GPU_RGBA32F, data, NULL);
|
GPUTexture *tex = GPU_texture_create_1d_array(ima->id.name + 2, width, 2, 1, GPU_RGBA32F, data);
|
||||||
GPU_texture_mipmap_mode(tex, false, false);
|
GPU_texture_mipmap_mode(tex, false, false);
|
||||||
|
|
||||||
MEM_freeN(data);
|
MEM_freeN(data);
|
||||||
@@ -180,9 +180,7 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
|
|||||||
const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH);
|
const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH);
|
||||||
/* Create Texture without content. */
|
/* Create Texture without content. */
|
||||||
GPUTexture *tex = IMB_touch_gpu_texture(
|
GPUTexture *tex = IMB_touch_gpu_texture(
|
||||||
main_ibuf, arraywidth, arrayheight, arraylayers, use_high_bitdepth);
|
ima->id.name + 2, main_ibuf, arraywidth, arrayheight, arraylayers, use_high_bitdepth);
|
||||||
|
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
|
|
||||||
/* Upload each tile one by one. */
|
/* Upload each tile one by one. */
|
||||||
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
|
||||||
@@ -225,8 +223,6 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
|
|||||||
GPU_texture_mipmap_mode(tex, false, true);
|
GPU_texture_mipmap_mode(tex, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU_texture_unbind(tex);
|
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +247,7 @@ static GPUTexture **get_image_gpu_texture_ptr(Image *ima,
|
|||||||
|
|
||||||
static GPUTexture *image_gpu_texture_error_create(eGPUTextureTarget textarget)
|
static GPUTexture *image_gpu_texture_error_create(eGPUTextureTarget textarget)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "GPUTexture: Blender Texture Not Loaded!\n");
|
||||||
switch (textarget) {
|
switch (textarget) {
|
||||||
case TEXTARGET_2D_ARRAY:
|
case TEXTARGET_2D_ARRAY:
|
||||||
return GPU_texture_create_error(2, true);
|
return GPU_texture_create_error(2, true);
|
||||||
@@ -320,12 +317,11 @@ static GPUTexture *image_get_gpu_texture(Image *ima,
|
|||||||
(ima ? (ima->alpha_mode != IMA_ALPHA_STRAIGHT) : false) :
|
(ima ? (ima->alpha_mode != IMA_ALPHA_STRAIGHT) : false) :
|
||||||
(ima ? (ima->alpha_mode == IMA_ALPHA_PREMUL) : true);
|
(ima ? (ima->alpha_mode == IMA_ALPHA_PREMUL) : true);
|
||||||
|
|
||||||
*tex = IMB_create_gpu_texture(ibuf_intern, use_high_bitdepth, store_premultiplied);
|
*tex = IMB_create_gpu_texture(
|
||||||
|
ima->id.name + 2, ibuf_intern, use_high_bitdepth, store_premultiplied);
|
||||||
|
|
||||||
if (GPU_mipmap_enabled()) {
|
if (GPU_mipmap_enabled()) {
|
||||||
GPU_texture_bind(*tex, 0);
|
|
||||||
GPU_texture_generate_mipmap(*tex);
|
GPU_texture_generate_mipmap(*tex);
|
||||||
GPU_texture_unbind(*tex);
|
|
||||||
if (ima) {
|
if (ima) {
|
||||||
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
|
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
|
||||||
}
|
}
|
||||||
@@ -666,8 +662,6 @@ static void gpu_texture_update_from_ibuf(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
|
|
||||||
if (scaled) {
|
if (scaled) {
|
||||||
/* Slower update where we first have to scale the input pixels. */
|
/* Slower update where we first have to scale the input pixels. */
|
||||||
if (tile != NULL) {
|
if (tile != NULL) {
|
||||||
|
@@ -1917,6 +1917,7 @@ GPUTexture *BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser)
|
|||||||
/* check if we have a valid image buffer */
|
/* check if we have a valid image buffer */
|
||||||
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser);
|
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser);
|
||||||
if (ibuf == NULL) {
|
if (ibuf == NULL) {
|
||||||
|
fprintf(stderr, "GPUTexture: Blender Texture Not Loaded!\n");
|
||||||
*tex = GPU_texture_create_error(2, false);
|
*tex = GPU_texture_create_error(2, false);
|
||||||
return *tex;
|
return *tex;
|
||||||
}
|
}
|
||||||
@@ -1924,7 +1925,7 @@ GPUTexture *BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser)
|
|||||||
/* This only means RGBA16F instead of RGBA32F. */
|
/* This only means RGBA16F instead of RGBA32F. */
|
||||||
const bool high_bitdepth = false;
|
const bool high_bitdepth = false;
|
||||||
const bool store_premultiplied = ibuf->rect_float ? false : true;
|
const bool store_premultiplied = ibuf->rect_float ? false : true;
|
||||||
*tex = IMB_create_gpu_texture(ibuf, high_bitdepth, store_premultiplied);
|
*tex = IMB_create_gpu_texture(clip->id.name + 2, ibuf, high_bitdepth, store_premultiplied);
|
||||||
|
|
||||||
/* Do not generate mips for movieclips... too slow. */
|
/* Do not generate mips for movieclips... too slow. */
|
||||||
GPU_texture_mipmap_mode(*tex, false, true);
|
GPU_texture_mipmap_mode(*tex, false, true);
|
||||||
|
@@ -500,7 +500,7 @@ static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl)
|
|||||||
ImBuf *ibuf = sl->equirect_radiance_buffer;
|
ImBuf *ibuf = sl->equirect_radiance_buffer;
|
||||||
|
|
||||||
sl->equirect_radiance_gputexture = GPU_texture_create_2d(
|
sl->equirect_radiance_gputexture = GPU_texture_create_2d(
|
||||||
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
|
"studiolight_radiance", ibuf->x, ibuf->y, 1, GPU_RGBA16F, ibuf->rect_float);
|
||||||
GPUTexture *tex = sl->equirect_radiance_gputexture;
|
GPUTexture *tex = sl->equirect_radiance_gputexture;
|
||||||
GPU_texture_filter_mode(tex, true);
|
GPU_texture_filter_mode(tex, true);
|
||||||
GPU_texture_wrap_mode(tex, true, true);
|
GPU_texture_wrap_mode(tex, true, true);
|
||||||
@@ -520,16 +520,9 @@ static void studiolight_create_matcap_gputexture(StudioLightImage *sli)
|
|||||||
copy_v3_v3(*offset3, *offset4);
|
copy_v3_v3(*offset3, *offset4);
|
||||||
}
|
}
|
||||||
|
|
||||||
sli->gputexture = GPU_texture_create_nD(ibuf->x,
|
sli->gputexture = GPU_texture_create_2d("matcap", ibuf->x, ibuf->y, 1, GPU_R11F_G11F_B10F, NULL);
|
||||||
ibuf->y,
|
GPU_texture_update(sli->gputexture, GPU_DATA_FLOAT, gpu_matcap_3components);
|
||||||
0,
|
|
||||||
2,
|
|
||||||
gpu_matcap_3components,
|
|
||||||
GPU_R11F_G11F_B10F,
|
|
||||||
GPU_DATA_FLOAT,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
MEM_SAFE_FREE(gpu_matcap_3components);
|
MEM_SAFE_FREE(gpu_matcap_3components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +555,7 @@ static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl)
|
|||||||
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED);
|
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED);
|
||||||
ImBuf *ibuf = sl->equirect_irradiance_buffer;
|
ImBuf *ibuf = sl->equirect_irradiance_buffer;
|
||||||
sl->equirect_irradiance_gputexture = GPU_texture_create_2d(
|
sl->equirect_irradiance_gputexture = GPU_texture_create_2d(
|
||||||
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
|
"studiolight_irradiance", ibuf->x, ibuf->y, 1, GPU_RGBA16F, ibuf->rect_float);
|
||||||
GPUTexture *tex = sl->equirect_irradiance_gputexture;
|
GPUTexture *tex = sl->equirect_irradiance_gputexture;
|
||||||
GPU_texture_filter_mode(tex, true);
|
GPU_texture_filter_mode(tex, true);
|
||||||
GPU_texture_wrap_mode(tex, true, true);
|
GPU_texture_wrap_mode(tex, true, true);
|
||||||
|
@@ -31,6 +31,7 @@ extern "C" {
|
|||||||
/* Search the value from LSB to MSB for a set bit. Returns index of this bit. */
|
/* Search the value from LSB to MSB for a set bit. Returns index of this bit. */
|
||||||
MINLINE int bitscan_forward_i(int a);
|
MINLINE int bitscan_forward_i(int a);
|
||||||
MINLINE unsigned int bitscan_forward_uint(unsigned int a);
|
MINLINE unsigned int bitscan_forward_uint(unsigned int a);
|
||||||
|
MINLINE unsigned int bitscan_forward_uint64(unsigned long long a);
|
||||||
|
|
||||||
/* Similar to above, but also clears the bit. */
|
/* Similar to above, but also clears the bit. */
|
||||||
MINLINE int bitscan_forward_clear_i(int *a);
|
MINLINE int bitscan_forward_clear_i(int *a);
|
||||||
@@ -39,6 +40,7 @@ MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a);
|
|||||||
/* Search the value from MSB to LSB for a set bit. Returns index of this bit. */
|
/* Search the value from MSB to LSB for a set bit. Returns index of this bit. */
|
||||||
MINLINE int bitscan_reverse_i(int a);
|
MINLINE int bitscan_reverse_i(int a);
|
||||||
MINLINE unsigned int bitscan_reverse_uint(unsigned int a);
|
MINLINE unsigned int bitscan_reverse_uint(unsigned int a);
|
||||||
|
MINLINE unsigned int bitscan_reverse_uint64(unsigned long long a);
|
||||||
|
|
||||||
/* Similar to above, but also clears the bit. */
|
/* Similar to above, but also clears the bit. */
|
||||||
MINLINE int bitscan_reverse_clear_i(int *a);
|
MINLINE int bitscan_reverse_clear_i(int *a);
|
||||||
|
@@ -338,6 +338,7 @@ MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RE
|
|||||||
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
|
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
MINLINE bool equals_v2v2_int(const int v1[2], const int v2[2]) ATTR_WARN_UNUSED_RESULT;
|
MINLINE bool equals_v2v2_int(const int v1[2], const int v2[2]) ATTR_WARN_UNUSED_RESULT;
|
||||||
|
MINLINE bool equals_v3v3_int(const int v1[3], const int v2[3]) ATTR_WARN_UNUSED_RESULT;
|
||||||
MINLINE bool equals_v4v4_int(const int v1[4], const int v2[4]) ATTR_WARN_UNUSED_RESULT;
|
MINLINE bool equals_v4v4_int(const int v1[4], const int v2[4]) ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
MINLINE bool compare_v2v2(const float a[2],
|
MINLINE bool compare_v2v2(const float a[2],
|
||||||
|
@@ -40,6 +40,18 @@ MINLINE unsigned int bitscan_forward_uint(unsigned int a)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MINLINE unsigned int bitscan_forward_uint64(unsigned long long a)
|
||||||
|
{
|
||||||
|
BLI_assert(a != 0);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
unsigned long ctz;
|
||||||
|
_BitScanForward64(&ctz, a);
|
||||||
|
return ctz;
|
||||||
|
#else
|
||||||
|
return (unsigned int)__builtin_ctz(a);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
MINLINE int bitscan_forward_i(int a)
|
MINLINE int bitscan_forward_i(int a)
|
||||||
{
|
{
|
||||||
return (int)bitscan_forward_uint((unsigned int)a);
|
return (int)bitscan_forward_uint((unsigned int)a);
|
||||||
@@ -69,6 +81,18 @@ MINLINE unsigned int bitscan_reverse_uint(unsigned int a)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MINLINE unsigned int bitscan_reverse_uint64(unsigned long long a)
|
||||||
|
{
|
||||||
|
BLI_assert(a != 0);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
unsigned long clz;
|
||||||
|
_BitScanReverse64(&clz, a);
|
||||||
|
return 31 - clz;
|
||||||
|
#else
|
||||||
|
return (unsigned int)__builtin_clzll(a);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
MINLINE int bitscan_reverse_i(int a)
|
MINLINE int bitscan_reverse_i(int a)
|
||||||
{
|
{
|
||||||
return (int)bitscan_reverse_uint((unsigned int)a);
|
return (int)bitscan_reverse_uint((unsigned int)a);
|
||||||
|
@@ -1313,6 +1313,11 @@ MINLINE bool equals_v2v2_int(const int v1[2], const int v2[2])
|
|||||||
return ((v1[0] == v2[0]) && (v1[1] == v2[1]));
|
return ((v1[0] == v2[0]) && (v1[1] == v2[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MINLINE bool equals_v3v3_int(const int v1[3], const int v2[3])
|
||||||
|
{
|
||||||
|
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]));
|
||||||
|
}
|
||||||
|
|
||||||
MINLINE bool equals_v4v4_int(const int v1[4], const int v2[4])
|
MINLINE bool equals_v4v4_int(const int v1[4], const int v2[4])
|
||||||
{
|
{
|
||||||
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3]));
|
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3]));
|
||||||
|
@@ -202,7 +202,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
|
|||||||
* Compute Mipmap texel alignment.
|
* Compute Mipmap texel alignment.
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
int mip_size[2];
|
int mip_size[3];
|
||||||
GPU_texture_get_mipmap_size(txl->color, i, mip_size);
|
GPU_texture_get_mipmap_size(txl->color, i, mip_size);
|
||||||
common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, i));
|
common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, i));
|
||||||
common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, i));
|
common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, i));
|
||||||
@@ -432,7 +432,7 @@ void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int l
|
|||||||
int minmax_size[3], depth_size[3];
|
int minmax_size[3], depth_size[3];
|
||||||
GPU_texture_get_mipmap_size(depth_src, 0, depth_size);
|
GPU_texture_get_mipmap_size(depth_src, 0, depth_size);
|
||||||
GPU_texture_get_mipmap_size(txl->maxzbuffer, 0, minmax_size);
|
GPU_texture_get_mipmap_size(txl->maxzbuffer, 0, minmax_size);
|
||||||
bool is_full_res_minmaxz = (minmax_size[0] == depth_size[0] && minmax_size[1] == depth_size[1]);
|
bool is_full_res_minmaxz = equals_v2v2_int(minmax_size, depth_size);
|
||||||
|
|
||||||
DRW_stats_group_start("Max buffer");
|
DRW_stats_group_start("Max buffer");
|
||||||
/* Copy depth buffer to max texture top level */
|
/* Copy depth buffer to max texture top level */
|
||||||
|
@@ -401,16 +401,9 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lcache->grid_tx.tex == NULL) {
|
if (lcache->grid_tx.tex == NULL) {
|
||||||
lcache->grid_tx.tex = GPU_texture_create_nD(lcache->grid_tx.tex_size[0],
|
lcache->grid_tx.tex = GPU_texture_create_2d_array(
|
||||||
lcache->grid_tx.tex_size[1],
|
"lightcache_irradiance", UNPACK3(lcache->grid_tx.tex_size), 1, IRRADIANCE_FORMAT, NULL);
|
||||||
lcache->grid_tx.tex_size[2],
|
GPU_texture_update(lcache->grid_tx.tex, GPU_DATA_UNSIGNED_BYTE, lcache->grid_tx.data);
|
||||||
2,
|
|
||||||
lcache->grid_tx.data,
|
|
||||||
IRRADIANCE_FORMAT,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (lcache->grid_tx.tex == NULL) {
|
if (lcache->grid_tx.tex == NULL) {
|
||||||
lcache->flag |= LIGHTCACHE_NOT_USABLE;
|
lcache->flag |= LIGHTCACHE_NOT_USABLE;
|
||||||
@@ -422,24 +415,19 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
|
|||||||
|
|
||||||
if (lcache->cube_tx.tex == NULL) {
|
if (lcache->cube_tx.tex == NULL) {
|
||||||
if (GPU_arb_texture_cube_map_array_is_supported()) {
|
if (GPU_arb_texture_cube_map_array_is_supported()) {
|
||||||
lcache->cube_tx.tex = GPU_texture_cube_create(lcache->cube_tx.tex_size[0],
|
lcache->cube_tx.tex = GPU_texture_create_cube_array("lightcache_cubemaps",
|
||||||
lcache->cube_tx.tex_size[2] / 6,
|
lcache->cube_tx.tex_size[0],
|
||||||
lcache->cube_tx.data,
|
lcache->cube_tx.tex_size[2] / 6,
|
||||||
GPU_R11F_G11F_B10F,
|
lcache->mips_len + 1,
|
||||||
GPU_DATA_10_11_11_REV,
|
GPU_R11F_G11F_B10F,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lcache->cube_tx.tex = GPU_texture_create_nD(lcache->cube_tx.tex_size[0],
|
lcache->cube_tx.tex = GPU_texture_create_2d_array("lightcache_cubemaps_fallback",
|
||||||
lcache->cube_tx.tex_size[1],
|
UNPACK3(lcache->cube_tx.tex_size),
|
||||||
lcache->cube_tx.tex_size[2],
|
lcache->mips_len + 1,
|
||||||
2,
|
GPU_R11F_G11F_B10F,
|
||||||
lcache->cube_tx.data,
|
NULL);
|
||||||
GPU_R11F_G11F_B10F,
|
|
||||||
GPU_DATA_10_11_11_REV,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lcache->cube_tx.tex == NULL) {
|
if (lcache->cube_tx.tex == NULL) {
|
||||||
@@ -447,9 +435,9 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int mip = 0; mip < lcache->mips_len; mip++) {
|
for (int mip = 0; mip <= lcache->mips_len; mip++) {
|
||||||
GPU_texture_add_mipmap(
|
const void *data = (mip == 0) ? lcache->cube_tx.data : lcache->cube_mips[mip - 1].data;
|
||||||
lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
|
GPU_texture_update_mipmap(lcache->cube_tx.tex, mip, GPU_DATA_10_11_11_REV, data);
|
||||||
}
|
}
|
||||||
GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
|
GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
|
||||||
}
|
}
|
||||||
|
@@ -468,7 +468,7 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
|
|||||||
GPU_vertbuf_use(mb_hair->psys[i].hair_pos[mb_step]);
|
GPU_vertbuf_use(mb_hair->psys[i].hair_pos[mb_step]);
|
||||||
|
|
||||||
mb_hair->psys[i].hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf(
|
mb_hair->psys[i].hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf(
|
||||||
mb_hair->psys[i].hair_pos[mb_step]);
|
"hair_pos_motion_blur", mb_hair->psys[i].hair_pos[mb_step]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -56,27 +56,13 @@ void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (txl->smaa_search_tx == NULL) {
|
if (txl->smaa_search_tx == NULL) {
|
||||||
txl->smaa_search_tx = GPU_texture_create_nD(SEARCHTEX_WIDTH,
|
txl->smaa_search_tx = GPU_texture_create_2d(
|
||||||
SEARCHTEX_HEIGHT,
|
"smaa_search", SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1, GPU_R8, NULL);
|
||||||
0,
|
GPU_texture_update(txl->smaa_search_tx, GPU_DATA_UNSIGNED_BYTE, searchTexBytes);
|
||||||
2,
|
|
||||||
searchTexBytes,
|
|
||||||
GPU_R8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
txl->smaa_area_tx = GPU_texture_create_nD(AREATEX_WIDTH,
|
txl->smaa_area_tx = GPU_texture_create_2d(
|
||||||
AREATEX_HEIGHT,
|
"smaa_area", AREATEX_WIDTH, AREATEX_HEIGHT, 1, GPU_RG8, NULL);
|
||||||
0,
|
GPU_texture_update(txl->smaa_area_tx, GPU_DATA_UNSIGNED_BYTE, areaTexBytes);
|
||||||
2,
|
|
||||||
areaTexBytes,
|
|
||||||
GPU_RG8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
GPU_texture_filter_mode(txl->smaa_search_tx, true);
|
GPU_texture_filter_mode(txl->smaa_search_tx, true);
|
||||||
GPU_texture_filter_mode(txl->smaa_area_tx, true);
|
GPU_texture_filter_mode(txl->smaa_area_tx, true);
|
||||||
|
@@ -143,11 +143,9 @@ void GPENCIL_render_init(GPENCIL_Data *vedata,
|
|||||||
int w = BLI_rcti_size_x(rect);
|
int w = BLI_rcti_size_x(rect);
|
||||||
int h = BLI_rcti_size_y(rect);
|
int h = BLI_rcti_size_y(rect);
|
||||||
if (pix_col) {
|
if (pix_col) {
|
||||||
GPU_texture_bind(txl->render_color_tx, 0);
|
|
||||||
GPU_texture_update_sub(txl->render_color_tx, GPU_DATA_FLOAT, pix_col, x, y, 0, w, h, 0);
|
GPU_texture_update_sub(txl->render_color_tx, GPU_DATA_FLOAT, pix_col, x, y, 0, w, h, 0);
|
||||||
}
|
}
|
||||||
if (pix_z) {
|
if (pix_z) {
|
||||||
GPU_texture_bind(txl->render_depth_tx, 0);
|
|
||||||
GPU_texture_update_sub(txl->render_depth_tx, GPU_DATA_FLOAT, pix_z, x, y, 0, w, h, 0);
|
GPU_texture_update_sub(txl->render_depth_tx, GPU_DATA_FLOAT, pix_z, x, y, 0, w, h, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -79,7 +79,8 @@ static void select_engine_framebuffer_setup(void)
|
|||||||
GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
|
GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
|
||||||
|
|
||||||
if (e_data.texture_u32 == NULL) {
|
if (e_data.texture_u32 == NULL) {
|
||||||
e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
|
e_data.texture_u32 = GPU_texture_create_2d(
|
||||||
|
"select_buf_ids", size[0], size[1], 1, GPU_R32UI, NULL);
|
||||||
GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
|
GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
|
||||||
|
|
||||||
GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
|
GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
|
||||||
|
@@ -242,27 +242,13 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
|
|||||||
|
|
||||||
/* TODO could be shared for all viewports. */
|
/* TODO could be shared for all viewports. */
|
||||||
if (txl->smaa_search_tx == NULL) {
|
if (txl->smaa_search_tx == NULL) {
|
||||||
txl->smaa_search_tx = GPU_texture_create_nD(SEARCHTEX_WIDTH,
|
txl->smaa_search_tx = GPU_texture_create_2d(
|
||||||
SEARCHTEX_HEIGHT,
|
"smaa_search", SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1, GPU_R8, NULL);
|
||||||
0,
|
GPU_texture_update(txl->smaa_search_tx, GPU_DATA_UNSIGNED_BYTE, searchTexBytes);
|
||||||
2,
|
|
||||||
searchTexBytes,
|
|
||||||
GPU_R8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
txl->smaa_area_tx = GPU_texture_create_nD(AREATEX_WIDTH,
|
txl->smaa_area_tx = GPU_texture_create_2d(
|
||||||
AREATEX_HEIGHT,
|
"smaa_area", AREATEX_WIDTH, AREATEX_HEIGHT, 1, GPU_RG8, NULL);
|
||||||
0,
|
GPU_texture_update(txl->smaa_area_tx, GPU_DATA_UNSIGNED_BYTE, areaTexBytes);
|
||||||
2,
|
|
||||||
areaTexBytes,
|
|
||||||
GPU_RG8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
GPU_texture_filter_mode(txl->smaa_search_tx, true);
|
GPU_texture_filter_mode(txl->smaa_search_tx, true);
|
||||||
GPU_texture_filter_mode(txl->smaa_area_tx, true);
|
GPU_texture_filter_mode(txl->smaa_area_tx, true);
|
||||||
|
@@ -79,8 +79,8 @@ static bool workbench_render_framebuffers_init(void)
|
|||||||
* the other views will reuse these buffers */
|
* the other views will reuse these buffers */
|
||||||
if (dtxl->color == NULL) {
|
if (dtxl->color == NULL) {
|
||||||
BLI_assert(dtxl->depth == NULL);
|
BLI_assert(dtxl->depth == NULL);
|
||||||
dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL);
|
dtxl->color = GPU_texture_create_2d("txl.color", UNPACK2(size), 1, GPU_RGBA16F, NULL);
|
||||||
dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL);
|
dtxl->depth = GPU_texture_create_2d("txl.depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dtxl->depth && dtxl->color)) {
|
if (!(dtxl->depth && dtxl->color)) {
|
||||||
|
@@ -45,9 +45,9 @@ void workbench_volume_engine_init(WORKBENCH_Data *vedata)
|
|||||||
if (txl->dummy_volume_tx == NULL) {
|
if (txl->dummy_volume_tx == NULL) {
|
||||||
const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, zero, NULL);
|
txl->dummy_volume_tx = GPU_texture_create_3d("dummy_volume", 1, 1, 1, 1, GPU_RGBA8, zero);
|
||||||
txl->dummy_shadow_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, one, NULL);
|
txl->dummy_shadow_tx = GPU_texture_create_3d("dummy_shadow", 1, 1, 1, 1, GPU_RGBA8, one);
|
||||||
txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, zero, NULL);
|
txl->dummy_coba_tx = GPU_texture_create_1d("dummy_coba", 1, 1, GPU_RGBA8, zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -192,7 +192,7 @@ static void hair_batch_cache_ensure_procedural_pos(Hair *hair, ParticleHairCache
|
|||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(cache->proc_point_buf);
|
GPU_vertbuf_use(cache->proc_point_buf);
|
||||||
|
|
||||||
cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf);
|
cache->point_tex = GPU_texture_create_from_vertbuf("hair_point", cache->proc_point_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hair_batch_cache_fill_strands_data(Hair *hair,
|
static void hair_batch_cache_fill_strands_data(Hair *hair,
|
||||||
@@ -230,10 +230,11 @@ static void hair_batch_cache_ensure_procedural_strand_data(Hair *hair, ParticleH
|
|||||||
|
|
||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(cache->proc_strand_buf);
|
GPU_vertbuf_use(cache->proc_strand_buf);
|
||||||
cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf);
|
cache->strand_tex = GPU_texture_create_from_vertbuf("hair_strand", cache->proc_strand_buf);
|
||||||
|
|
||||||
GPU_vertbuf_use(cache->proc_strand_seg_buf);
|
GPU_vertbuf_use(cache->proc_strand_seg_buf);
|
||||||
cache->strand_seg_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_seg_buf);
|
cache->strand_seg_tex = GPU_texture_create_from_vertbuf("hair_strand_seg",
|
||||||
|
cache->proc_strand_seg_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
|
static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
|
||||||
@@ -252,7 +253,8 @@ static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *c
|
|||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(cache->final[subdiv].proc_buf);
|
GPU_vertbuf_use(cache->final[subdiv].proc_buf);
|
||||||
|
|
||||||
cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf);
|
cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc",
|
||||||
|
cache->final[subdiv].proc_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hair_batch_cache_fill_segments_indices(Hair *hair,
|
static void hair_batch_cache_fill_segments_indices(Hair *hair,
|
||||||
|
@@ -809,7 +809,8 @@ static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCach
|
|||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(cache->final[subdiv].proc_buf);
|
GPU_vertbuf_use(cache->final[subdiv].proc_buf);
|
||||||
|
|
||||||
cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf);
|
cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("part_proc",
|
||||||
|
cache->final[subdiv].proc_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit,
|
static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit,
|
||||||
@@ -1008,18 +1009,19 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
|
|||||||
|
|
||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(cache->proc_strand_buf);
|
GPU_vertbuf_use(cache->proc_strand_buf);
|
||||||
cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf);
|
cache->strand_tex = GPU_texture_create_from_vertbuf("part_strand", cache->proc_strand_buf);
|
||||||
|
|
||||||
GPU_vertbuf_use(cache->proc_strand_seg_buf);
|
GPU_vertbuf_use(cache->proc_strand_seg_buf);
|
||||||
cache->strand_seg_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_seg_buf);
|
cache->strand_seg_tex = GPU_texture_create_from_vertbuf("part_strand_seg",
|
||||||
|
cache->proc_strand_seg_buf);
|
||||||
|
|
||||||
for (int i = 0; i < cache->num_uv_layers; i++) {
|
for (int i = 0; i < cache->num_uv_layers; i++) {
|
||||||
GPU_vertbuf_use(cache->proc_uv_buf[i]);
|
GPU_vertbuf_use(cache->proc_uv_buf[i]);
|
||||||
cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]);
|
cache->uv_tex[i] = GPU_texture_create_from_vertbuf("part_uv", cache->proc_uv_buf[i]);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < cache->num_col_layers; i++) {
|
for (int i = 0; i < cache->num_col_layers; i++) {
|
||||||
GPU_vertbuf_use(cache->proc_col_buf[i]);
|
GPU_vertbuf_use(cache->proc_col_buf[i]);
|
||||||
cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]);
|
cache->col_tex[i] = GPU_texture_create_from_vertbuf("part_col", cache->proc_col_buf[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1109,7 +1111,7 @@ static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit,
|
|||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(cache->proc_point_buf);
|
GPU_vertbuf_use(cache->proc_point_buf);
|
||||||
|
|
||||||
cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf);
|
cache->point_tex = GPU_texture_create_from_vertbuf("part_point", cache->proc_point_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
|
static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
|
||||||
|
@@ -258,17 +258,12 @@ static DRWVolumeGrid *volume_grid_cache_get(Volume *volume,
|
|||||||
BKE_volume_grid_dense_voxels(volume, grid, dense_min, dense_max, voxels);
|
BKE_volume_grid_dense_voxels(volume, grid, dense_min, dense_max, voxels);
|
||||||
|
|
||||||
/* Create GPU texture. */
|
/* Create GPU texture. */
|
||||||
cache_grid->texture = GPU_texture_create_3d(resolution[0],
|
eGPUTextureFormat format = (channels == 3) ? GPU_RGB16F : GPU_R16F;
|
||||||
resolution[1],
|
cache_grid->texture = GPU_texture_create_3d(
|
||||||
resolution[2],
|
"volume_grid", UNPACK3(resolution), 1, format, voxels);
|
||||||
(channels == 3) ? GPU_RGB16F : GPU_R16F,
|
|
||||||
voxels,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
GPU_texture_bind(cache_grid->texture, 0);
|
|
||||||
GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
|
GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
|
||||||
GPU_texture_wrap_mode(cache_grid->texture, false, false);
|
GPU_texture_wrap_mode(cache_grid->texture, false, false);
|
||||||
GPU_texture_unbind(cache_grid->texture);
|
|
||||||
|
|
||||||
MEM_freeN(voxels);
|
MEM_freeN(voxels);
|
||||||
|
|
||||||
|
@@ -53,10 +53,10 @@ void DRW_transform_none(GPUTexture *tex)
|
|||||||
GPUBatch *geom = DRW_cache_fullscreen_quad_get();
|
GPUBatch *geom = DRW_cache_fullscreen_quad_get();
|
||||||
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE_COLOR);
|
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE_COLOR);
|
||||||
GPU_batch_uniform_4f(geom, "color", 1.0f, 1.0f, 1.0f, 1.0f);
|
GPU_batch_uniform_4f(geom, "color", 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
GPU_batch_uniform_1i(geom, "image", 0);
|
GPU_batch_texture_bind(geom, "image", tex);
|
||||||
|
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
GPU_batch_draw(geom);
|
GPU_batch_draw(geom);
|
||||||
|
|
||||||
GPU_texture_unbind(tex);
|
GPU_texture_unbind(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -238,7 +238,7 @@ void DRW_globals_update(void)
|
|||||||
|
|
||||||
BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size);
|
BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size);
|
||||||
|
|
||||||
G_draw.ramp = GPU_texture_create_1d(col_size, GPU_RGBA8, colors, NULL);
|
G_draw.ramp = GPU_texture_create_1d("ramp", col_size, 1, GPU_RGBA8, colors);
|
||||||
|
|
||||||
MEM_freeN(colors);
|
MEM_freeN(colors);
|
||||||
}
|
}
|
||||||
@@ -503,12 +503,11 @@ static void DRW_evaluate_weight_to_color(const float weight, float result[4])
|
|||||||
|
|
||||||
static GPUTexture *DRW_create_weight_colorramp_texture(void)
|
static GPUTexture *DRW_create_weight_colorramp_texture(void)
|
||||||
{
|
{
|
||||||
char error[256];
|
|
||||||
float pixels[256][4];
|
float pixels[256][4];
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
DRW_evaluate_weight_to_color(i / 255.0f, pixels[i]);
|
DRW_evaluate_weight_to_color(i / 255.0f, pixels[i]);
|
||||||
pixels[i][3] = 1.0f;
|
pixels[i][3] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GPU_texture_create_1d(256, GPU_SRGB8_A8, pixels[0], error);
|
return GPU_texture_create_1d("weight_color_ramp", 256, 1, GPU_SRGB8_A8, pixels[0]);
|
||||||
}
|
}
|
||||||
|
@@ -117,7 +117,7 @@ static GPUTexture *create_transfer_function(int type, const struct ColorBand *co
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_SRGB8_A8, data, NULL);
|
GPUTexture *tex = GPU_texture_create_1d("transf_func", TFUNC_WIDTH, 1, GPU_SRGB8_A8, data);
|
||||||
|
|
||||||
MEM_freeN(data);
|
MEM_freeN(data);
|
||||||
|
|
||||||
@@ -128,9 +128,100 @@ static void swizzle_texture_channel_single(GPUTexture *tex)
|
|||||||
{
|
{
|
||||||
/* Swizzle texture channels so that we get useful RGBA values when sampling
|
/* Swizzle texture channels so that we get useful RGBA values when sampling
|
||||||
* a texture with fewer channels, e.g. when using density as color. */
|
* a texture with fewer channels, e.g. when using density as color. */
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
GPU_texture_swizzle_set(tex, "rrr1");
|
GPU_texture_swizzle_set(tex, "rrr1");
|
||||||
GPU_texture_unbind(tex);
|
}
|
||||||
|
|
||||||
|
static float *rescale_3d(const int dim[3],
|
||||||
|
const int final_dim[3],
|
||||||
|
int channels,
|
||||||
|
const float *fpixels)
|
||||||
|
{
|
||||||
|
const uint w = dim[0], h = dim[1], d = dim[2];
|
||||||
|
const uint fw = final_dim[0], fh = final_dim[1], fd = final_dim[2];
|
||||||
|
const uint xf = w / fw, yf = h / fh, zf = d / fd;
|
||||||
|
const uint pixel_count = fw * fh * fd;
|
||||||
|
float *nfpixels = (float *)MEM_mallocN(channels * sizeof(float) * pixel_count, __func__);
|
||||||
|
|
||||||
|
if (nfpixels) {
|
||||||
|
printf("Performance: You need to scale a 3D texture, feel the pain!\n");
|
||||||
|
|
||||||
|
for (uint k = 0; k < fd; k++) {
|
||||||
|
for (uint j = 0; j < fh; j++) {
|
||||||
|
for (uint i = 0; i < fw; i++) {
|
||||||
|
/* Obviously doing nearest filtering here,
|
||||||
|
* it's going to be slow in any case, let's not make it worse. */
|
||||||
|
float xb = i * xf;
|
||||||
|
float yb = j * yf;
|
||||||
|
float zb = k * zf;
|
||||||
|
uint offset = k * (fw * fh) + i * fh + j;
|
||||||
|
uint offset_orig = (zb) * (w * h) + (xb)*h + (yb);
|
||||||
|
|
||||||
|
if (channels == 4) {
|
||||||
|
nfpixels[offset * 4] = fpixels[offset_orig * 4];
|
||||||
|
nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
|
||||||
|
nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
|
||||||
|
nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
|
||||||
|
}
|
||||||
|
else if (channels == 1) {
|
||||||
|
nfpixels[offset] = fpixels[offset_orig];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nfpixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Will resize input to fit GL system limits. */
|
||||||
|
static GPUTexture *create_volume_texture(const int dim[3],
|
||||||
|
eGPUTextureFormat format,
|
||||||
|
const float *data)
|
||||||
|
{
|
||||||
|
GPUTexture *tex = NULL;
|
||||||
|
int final_dim[3] = {UNPACK3(dim)};
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
tex = GPU_texture_create_3d("volume", UNPACK3(final_dim), 1, format, NULL);
|
||||||
|
|
||||||
|
if (tex != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final_dim[0] == 1 && final_dim[1] == 1 && final_dim[2] == 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
final_dim[i] = max_ii(1, final_dim[i] / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tex == NULL) {
|
||||||
|
printf("Error: Could not create 3D texture.\n");
|
||||||
|
tex = GPU_texture_create_error(3, false);
|
||||||
|
}
|
||||||
|
else if (equals_v3v3_int(dim, final_dim)) {
|
||||||
|
/* No need to resize, just upload the data. */
|
||||||
|
GPU_texture_update_sub(tex, GPU_DATA_FLOAT, data, 0, 0, 0, UNPACK3(final_dim));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* We need to resize the input. */
|
||||||
|
int channels = (format == GPU_R8) ? 1 : 4;
|
||||||
|
float *rescaled_data = rescale_3d(dim, final_dim, channels, data);
|
||||||
|
if (rescaled_data) {
|
||||||
|
GPU_texture_update_sub(tex, GPU_DATA_FLOAT, rescaled_data, 0, 0, 0, UNPACK3(final_dim));
|
||||||
|
MEM_freeN(rescaled_data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Error: Could not allocate rescaled 3d texture!\n");
|
||||||
|
GPU_texture_free(tex);
|
||||||
|
tex = GPU_texture_create_error(3, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GPUTexture *create_field_texture(FluidDomainSettings *fds)
|
static GPUTexture *create_field_texture(FluidDomainSettings *fds)
|
||||||
@@ -184,9 +275,7 @@ static GPUTexture *create_field_texture(FluidDomainSettings *fds)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_nD(
|
GPUTexture *tex = create_volume_texture(fds->res, GPU_R8, field);
|
||||||
UNPACK3(fds->res), 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
|
|
||||||
|
|
||||||
swizzle_texture_channel_single(tex);
|
swizzle_texture_channel_single(tex);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
@@ -203,11 +292,8 @@ static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres)
|
|||||||
data = manta_smoke_get_density(fds->fluid);
|
data = manta_smoke_get_density(fds->fluid);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_nD(
|
GPUTexture *tex = create_volume_texture(dim, GPU_R8, data);
|
||||||
UNPACK3(dim), 3, data, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
|
|
||||||
|
|
||||||
swizzle_texture_channel_single(tex);
|
swizzle_texture_channel_single(tex);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,8 +321,7 @@ static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres)
|
|||||||
manta_smoke_get_rgba(fds->fluid, data, 0);
|
manta_smoke_get_rgba(fds->fluid, data, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_nD(
|
GPUTexture *tex = create_volume_texture(dim, GPU_RGBA8, data);
|
||||||
dim[0], dim[1], dim[2], 3, data, GPU_RGBA8, GPU_DATA_FLOAT, 0, true, NULL);
|
|
||||||
|
|
||||||
MEM_freeN(data);
|
MEM_freeN(data);
|
||||||
|
|
||||||
@@ -261,11 +346,8 @@ static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres)
|
|||||||
source = manta_smoke_get_flame(fds->fluid);
|
source = manta_smoke_get_flame(fds->fluid);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_nD(
|
GPUTexture *tex = create_volume_texture(dim, GPU_R8, source);
|
||||||
dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
|
|
||||||
|
|
||||||
swizzle_texture_channel_single(tex);
|
swizzle_texture_channel_single(tex);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,14 +438,8 @@ void DRW_smoke_ensure(FluidModifierData *fmd, int highres)
|
|||||||
fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
|
fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
|
||||||
}
|
}
|
||||||
if (!fds->tex_shadow) {
|
if (!fds->tex_shadow) {
|
||||||
fds->tex_shadow = GPU_texture_create_nD(UNPACK3(fds->res),
|
fds->tex_shadow = create_volume_texture(
|
||||||
3,
|
fds->res, GPU_R8, manta_smoke_get_shadow(fds->fluid));
|
||||||
manta_smoke_get_shadow(fds->fluid),
|
|
||||||
GPU_R8,
|
|
||||||
GPU_DATA_FLOAT,
|
|
||||||
0,
|
|
||||||
true,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_FLUID */
|
#endif /* WITH_FLUID */
|
||||||
@@ -386,9 +462,9 @@ void DRW_smoke_ensure_velocity(FluidModifierData *fmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!fds->tex_velocity_x) {
|
if (!fds->tex_velocity_x) {
|
||||||
fds->tex_velocity_x = GPU_texture_create_3d(UNPACK3(fds->res), GPU_R16F, vel_x, NULL);
|
fds->tex_velocity_x = GPU_texture_create_3d("velx", UNPACK3(fds->res), 1, GPU_R16F, vel_x);
|
||||||
fds->tex_velocity_y = GPU_texture_create_3d(UNPACK3(fds->res), GPU_R16F, vel_y, NULL);
|
fds->tex_velocity_y = GPU_texture_create_3d("vely", UNPACK3(fds->res), 1, GPU_R16F, vel_y);
|
||||||
fds->tex_velocity_z = GPU_texture_create_3d(UNPACK3(fds->res), GPU_R16F, vel_z, NULL);
|
fds->tex_velocity_z = GPU_texture_create_3d("velz", UNPACK3(fds->res), 1, GPU_R16F, vel_z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_FLUID */
|
#endif /* WITH_FLUID */
|
||||||
|
@@ -120,7 +120,7 @@ void DRW_hair_init(void)
|
|||||||
/* Create vbo immediately to bind to texture buffer. */
|
/* Create vbo immediately to bind to texture buffer. */
|
||||||
GPU_vertbuf_use(g_dummy_vbo);
|
GPU_vertbuf_use(g_dummy_vbo);
|
||||||
|
|
||||||
g_dummy_texture = GPU_texture_create_from_vertbuf(g_dummy_vbo);
|
g_dummy_texture = GPU_texture_create_from_vertbuf("hair_dummy_attr", g_dummy_vbo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1929,7 +1929,7 @@ static void draw_select_framebuffer_depth_only_setup(const int size[2])
|
|||||||
|
|
||||||
if (g_select_buffer.texture_depth == NULL) {
|
if (g_select_buffer.texture_depth == NULL) {
|
||||||
g_select_buffer.texture_depth = GPU_texture_create_2d(
|
g_select_buffer.texture_depth = GPU_texture_create_2d(
|
||||||
size[0], size[1], GPU_DEPTH_COMPONENT24, NULL, NULL);
|
"select_depth", size[0], size[1], 1, GPU_DEPTH_COMPONENT24, NULL);
|
||||||
|
|
||||||
GPU_framebuffer_texture_attach(
|
GPU_framebuffer_texture_attach(
|
||||||
g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
|
g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
|
||||||
|
@@ -67,9 +67,7 @@ void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
|
|||||||
|
|
||||||
if (flags & DRW_TEX_MIPMAP) {
|
if (flags & DRW_TEX_MIPMAP) {
|
||||||
GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
|
GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
GPU_texture_generate_mipmap(tex);
|
GPU_texture_generate_mipmap(tex);
|
||||||
GPU_texture_unbind(tex);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
|
GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
|
||||||
@@ -83,7 +81,8 @@ GPUTexture *DRW_texture_create_1d(int w,
|
|||||||
DRWTextureFlag flags,
|
DRWTextureFlag flags,
|
||||||
const float *fpixels)
|
const float *fpixels)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = GPU_texture_create_1d(w, format, fpixels, NULL);
|
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
|
||||||
|
GPUTexture *tex = GPU_texture_create_1d(__func__, w, mips, format, fpixels);
|
||||||
drw_texture_set_parameters(tex, flags);
|
drw_texture_set_parameters(tex, flags);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
@@ -92,7 +91,8 @@ GPUTexture *DRW_texture_create_1d(int w,
|
|||||||
GPUTexture *DRW_texture_create_2d(
|
GPUTexture *DRW_texture_create_2d(
|
||||||
int w, int h, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
int w, int h, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = GPU_texture_create_2d(w, h, format, fpixels, NULL);
|
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
|
||||||
|
GPUTexture *tex = GPU_texture_create_2d(__func__, w, h, mips, format, fpixels);
|
||||||
drw_texture_set_parameters(tex, flags);
|
drw_texture_set_parameters(tex, flags);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
@@ -101,7 +101,8 @@ GPUTexture *DRW_texture_create_2d(
|
|||||||
GPUTexture *DRW_texture_create_2d_array(
|
GPUTexture *DRW_texture_create_2d_array(
|
||||||
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = GPU_texture_create_2d_array(w, h, d, format, fpixels, NULL);
|
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
|
||||||
|
GPUTexture *tex = GPU_texture_create_2d_array(__func__, w, h, d, mips, format, fpixels);
|
||||||
drw_texture_set_parameters(tex, flags);
|
drw_texture_set_parameters(tex, flags);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
@@ -110,7 +111,8 @@ GPUTexture *DRW_texture_create_2d_array(
|
|||||||
GPUTexture *DRW_texture_create_3d(
|
GPUTexture *DRW_texture_create_3d(
|
||||||
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = GPU_texture_create_3d(w, h, d, format, fpixels, NULL);
|
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
|
||||||
|
GPUTexture *tex = GPU_texture_create_3d(__func__, w, h, d, mips, format, fpixels);
|
||||||
drw_texture_set_parameters(tex, flags);
|
drw_texture_set_parameters(tex, flags);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
@@ -121,7 +123,8 @@ GPUTexture *DRW_texture_create_cube(int w,
|
|||||||
DRWTextureFlag flags,
|
DRWTextureFlag flags,
|
||||||
const float *fpixels)
|
const float *fpixels)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = GPU_texture_create_cube(w, format, fpixels, NULL);
|
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
|
||||||
|
GPUTexture *tex = GPU_texture_create_cube(__func__, w, mips, format, fpixels);
|
||||||
drw_texture_set_parameters(tex, flags);
|
drw_texture_set_parameters(tex, flags);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
@@ -129,7 +132,8 @@ GPUTexture *DRW_texture_create_cube(int w,
|
|||||||
GPUTexture *DRW_texture_create_cube_array(
|
GPUTexture *DRW_texture_create_cube_array(
|
||||||
int w, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
int w, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = GPU_texture_create_cube_array(w, d, format, fpixels, NULL);
|
int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
|
||||||
|
GPUTexture *tex = GPU_texture_create_cube_array(__func__, w, d, mips, format, fpixels);
|
||||||
drw_texture_set_parameters(tex, flags);
|
drw_texture_set_parameters(tex, flags);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
@@ -172,9 +176,7 @@ void DRW_texture_ensure_2d(
|
|||||||
|
|
||||||
void DRW_texture_generate_mipmaps(GPUTexture *tex)
|
void DRW_texture_generate_mipmaps(GPUTexture *tex)
|
||||||
{
|
{
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
GPU_texture_generate_mipmap(tex);
|
GPU_texture_generate_mipmap(tex);
|
||||||
GPU_texture_unbind(tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DRW_texture_free(GPUTexture *tex)
|
void DRW_texture_free(GPUTexture *tex)
|
||||||
|
@@ -868,31 +868,16 @@ void UI_icons_reload_internal_textures(void)
|
|||||||
icongltex.invw = 1.0f / b32buf->x;
|
icongltex.invw = 1.0f / b32buf->x;
|
||||||
icongltex.invh = 1.0f / b32buf->y;
|
icongltex.invh = 1.0f / b32buf->y;
|
||||||
|
|
||||||
icongltex.tex[0] = GPU_texture_create_nD(b32buf->x,
|
icongltex.tex[0] = GPU_texture_create_2d("icons", b32buf->x, b32buf->y, 2, GPU_RGBA8, NULL);
|
||||||
b32buf->y,
|
GPU_texture_update_mipmap(icongltex.tex[0], 0, GPU_DATA_UNSIGNED_BYTE, b32buf->rect);
|
||||||
0,
|
GPU_texture_update_mipmap(icongltex.tex[0], 1, GPU_DATA_UNSIGNED_BYTE, b16buf->rect);
|
||||||
2,
|
|
||||||
b32buf->rect,
|
|
||||||
GPU_RGBA8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
GPU_texture_add_mipmap(icongltex.tex[0], GPU_DATA_UNSIGNED_BYTE, 1, b16buf->rect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_icons_with_border && icongltex.tex[1] == NULL) {
|
if (need_icons_with_border && icongltex.tex[1] == NULL) {
|
||||||
icongltex.tex[1] = GPU_texture_create_nD(b32buf_border->x,
|
icongltex.tex[1] = GPU_texture_create_2d(
|
||||||
b32buf_border->y,
|
"icons_border", b32buf_border->x, b32buf_border->y, 2, GPU_RGBA8, NULL);
|
||||||
0,
|
GPU_texture_update_mipmap(icongltex.tex[1], 0, GPU_DATA_UNSIGNED_BYTE, b32buf_border->rect);
|
||||||
2,
|
GPU_texture_update_mipmap(icongltex.tex[1], 1, GPU_DATA_UNSIGNED_BYTE, b16buf_border->rect);
|
||||||
b32buf_border->rect,
|
|
||||||
GPU_RGBA8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
GPU_texture_add_mipmap(icongltex.tex[1], GPU_DATA_UNSIGNED_BYTE, 1, b16buf_border->rect);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1569,8 +1554,7 @@ static void icon_draw_cache_texture_flush_ex(GPUTexture *texture,
|
|||||||
const int img_binding = GPU_shader_get_texture_binding(shader, "image");
|
const int img_binding = GPU_shader_get_texture_binding(shader, "image");
|
||||||
const int data_loc = GPU_shader_get_uniform(shader, "calls_data");
|
const int data_loc = GPU_shader_get_uniform(shader, "calls_data");
|
||||||
|
|
||||||
GPU_texture_bind(texture, img_binding);
|
GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false);
|
||||||
GPU_sampler_icon_bind(img_binding);
|
|
||||||
GPU_shader_uniform_vector(
|
GPU_shader_uniform_vector(
|
||||||
shader, data_loc, 4, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
|
shader, data_loc, 4, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
|
||||||
|
|
||||||
@@ -1721,8 +1705,7 @@ static void icon_draw_texture(float x,
|
|||||||
GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2});
|
GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2});
|
||||||
GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h});
|
GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h});
|
||||||
|
|
||||||
GPU_texture_bind(texture, img_binding);
|
GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false);
|
||||||
GPU_sampler_icon_bind(img_binding);
|
|
||||||
|
|
||||||
GPUBatch *quad = GPU_batch_preset_quad();
|
GPUBatch *quad = GPU_batch_preset_quad();
|
||||||
GPU_batch_set_shader(quad, shader);
|
GPU_batch_set_shader(quad, shader);
|
||||||
|
@@ -132,7 +132,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
|
|||||||
eGPUDataFormat gpu_data = (use_float_data) ? GPU_DATA_FLOAT : GPU_DATA_UNSIGNED_BYTE;
|
eGPUDataFormat gpu_data = (use_float_data) ? GPU_DATA_FLOAT : GPU_DATA_UNSIGNED_BYTE;
|
||||||
size_t stride = components * ((use_float_data) ? sizeof(float) : sizeof(uchar));
|
size_t stride = components * ((use_float_data) ? sizeof(float) : sizeof(uchar));
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_2d(tex_w, tex_h, gpu_format, NULL, NULL);
|
GPUTexture *tex = GPU_texture_create_2d("immDrawPixels", tex_w, tex_h, 1, gpu_format, NULL);
|
||||||
|
|
||||||
GPU_texture_filter_mode(tex, use_filter);
|
GPU_texture_filter_mode(tex, use_filter);
|
||||||
GPU_texture_wrap_mode(tex, false, true);
|
GPU_texture_wrap_mode(tex, false, true);
|
||||||
|
@@ -348,13 +348,12 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
|
|||||||
|
|
||||||
if (!target->overlay_texture) {
|
if (!target->overlay_texture) {
|
||||||
eGPUTextureFormat format = col ? GPU_RGBA8 : GPU_R8;
|
eGPUTextureFormat format = col ? GPU_RGBA8 : GPU_R8;
|
||||||
target->overlay_texture = GPU_texture_create_nD(
|
target->overlay_texture = GPU_texture_create_2d(
|
||||||
size, size, 0, 2, buffer, format, GPU_DATA_UNSIGNED_BYTE, 0, false, NULL);
|
"paint_cursor_overlay", size, size, 1, format, NULL);
|
||||||
|
GPU_texture_update(target->overlay_texture, GPU_DATA_UNSIGNED_BYTE, buffer);
|
||||||
|
|
||||||
if (!col) {
|
if (!col) {
|
||||||
GPU_texture_bind(target->overlay_texture, 0);
|
|
||||||
GPU_texture_swizzle_set(target->overlay_texture, "rrrr");
|
GPU_texture_swizzle_set(target->overlay_texture, "rrrr");
|
||||||
GPU_texture_unbind(target->overlay_texture);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,12 +467,11 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
|
|||||||
BLI_task_parallel_range(0, size, &data, load_tex_cursor_task_cb, &settings);
|
BLI_task_parallel_range(0, size, &data, load_tex_cursor_task_cb, &settings);
|
||||||
|
|
||||||
if (!cursor_snap.overlay_texture) {
|
if (!cursor_snap.overlay_texture) {
|
||||||
cursor_snap.overlay_texture = GPU_texture_create_nD(
|
cursor_snap.overlay_texture = GPU_texture_create_2d(
|
||||||
size, size, 0, 2, buffer, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, NULL);
|
"cursor_snap_overaly", size, size, 1, GPU_R8, NULL);
|
||||||
|
GPU_texture_update(cursor_snap.overlay_texture, GPU_DATA_UNSIGNED_BYTE, buffer);
|
||||||
|
|
||||||
GPU_texture_bind(cursor_snap.overlay_texture, 0);
|
|
||||||
GPU_texture_swizzle_set(cursor_snap.overlay_texture, "rrrr");
|
GPU_texture_swizzle_set(cursor_snap.overlay_texture, "rrrr");
|
||||||
GPU_texture_unbind(cursor_snap.overlay_texture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
|
@@ -1211,16 +1211,9 @@ static void draw_plane_marker_image(Scene *scene,
|
|||||||
GPU_blend(GPU_BLEND_ALPHA);
|
GPU_blend(GPU_BLEND_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *texture = GPU_texture_create_nD(ibuf->x,
|
GPUTexture *texture = GPU_texture_create_2d(
|
||||||
ibuf->y,
|
"plane_marker_image", ibuf->x, ibuf->y, 1, GPU_RGBA8, NULL);
|
||||||
0,
|
GPU_texture_update(texture, GPU_DATA_UNSIGNED_BYTE, display_buffer);
|
||||||
2,
|
|
||||||
display_buffer,
|
|
||||||
GPU_RGBA8,
|
|
||||||
GPU_DATA_UNSIGNED_BYTE,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
NULL);
|
|
||||||
GPU_texture_filter_mode(texture, false);
|
GPU_texture_filter_mode(texture, false);
|
||||||
|
|
||||||
GPU_matrix_push();
|
GPU_matrix_push();
|
||||||
|
@@ -1639,8 +1639,9 @@ static void sequencer_draw_display_buffer(const bContext *C,
|
|||||||
GPU_matrix_identity_projection_set();
|
GPU_matrix_identity_projection_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *texture = GPU_texture_create_nD(
|
GPUTexture *texture = GPU_texture_create_2d(
|
||||||
ibuf->x, ibuf->y, 0, 2, display_buffer, format, data, 0, false, NULL);
|
"seq_display_buf", ibuf->x, ibuf->y, 1, format, NULL);
|
||||||
|
GPU_texture_update(texture, data, display_buffer);
|
||||||
GPU_texture_filter_mode(texture, false);
|
GPU_texture_filter_mode(texture, false);
|
||||||
|
|
||||||
GPU_texture_bind(texture, 0);
|
GPU_texture_bind(texture, 0);
|
||||||
|
@@ -96,6 +96,7 @@ set(SRC
|
|||||||
opengl/gl_shader.cc
|
opengl/gl_shader.cc
|
||||||
opengl/gl_shader_interface.cc
|
opengl/gl_shader_interface.cc
|
||||||
opengl/gl_state.cc
|
opengl/gl_state.cc
|
||||||
|
opengl/gl_texture.cc
|
||||||
opengl/gl_uniform_buffer.cc
|
opengl/gl_uniform_buffer.cc
|
||||||
opengl/gl_vertex_array.cc
|
opengl/gl_vertex_array.cc
|
||||||
|
|
||||||
@@ -143,6 +144,7 @@ set(SRC
|
|||||||
intern/gpu_shader_private.hh
|
intern/gpu_shader_private.hh
|
||||||
intern/gpu_shader_interface.hh
|
intern/gpu_shader_interface.hh
|
||||||
intern/gpu_state_private.hh
|
intern/gpu_state_private.hh
|
||||||
|
intern/gpu_texture_private.hh
|
||||||
intern/gpu_uniform_buffer_private.hh
|
intern/gpu_uniform_buffer_private.hh
|
||||||
intern/gpu_vertex_format_private.h
|
intern/gpu_vertex_format_private.h
|
||||||
|
|
||||||
|
@@ -146,6 +146,8 @@ void GPU_batch_program_set_builtin_with_config(GPUBatch *batch,
|
|||||||
GPU_shader_uniform_4fv_array((batch)->shader, name, len, val);
|
GPU_shader_uniform_4fv_array((batch)->shader, name, len, val);
|
||||||
#define GPU_batch_uniform_mat4(batch, name, val) \
|
#define GPU_batch_uniform_mat4(batch, name, val) \
|
||||||
GPU_shader_uniform_mat4((batch)->shader, name, val);
|
GPU_shader_uniform_mat4((batch)->shader, name, val);
|
||||||
|
#define GPU_batch_texture_bind(batch, name, tex) \
|
||||||
|
GPU_texture_bind(tex, GPU_shader_get_texture_binding((batch)->shader, name));
|
||||||
|
|
||||||
void GPU_batch_draw(GPUBatch *batch);
|
void GPU_batch_draw(GPUBatch *batch);
|
||||||
void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count);
|
void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count);
|
||||||
|
@@ -30,6 +30,7 @@ extern "C" {
|
|||||||
/* GPU extensions support */
|
/* GPU extensions support */
|
||||||
|
|
||||||
int GPU_max_texture_size(void);
|
int GPU_max_texture_size(void);
|
||||||
|
int GPU_max_texture_3d_size(void);
|
||||||
int GPU_max_texture_layers(void);
|
int GPU_max_texture_layers(void);
|
||||||
int GPU_max_textures(void);
|
int GPU_max_textures(void);
|
||||||
int GPU_max_textures_vert(void);
|
int GPU_max_textures_vert(void);
|
||||||
|
@@ -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,
|
||||||
|
@@ -44,6 +44,7 @@ typedef struct GPUTexture GPUTexture;
|
|||||||
* - All states are created at startup to avoid runtime costs.
|
* - All states are created at startup to avoid runtime costs.
|
||||||
*/
|
*/
|
||||||
typedef enum eGPUSamplerState {
|
typedef enum eGPUSamplerState {
|
||||||
|
GPU_SAMPLER_DEFAULT = 0,
|
||||||
GPU_SAMPLER_FILTER = (1 << 0),
|
GPU_SAMPLER_FILTER = (1 << 0),
|
||||||
GPU_SAMPLER_MIPMAP = (1 << 1),
|
GPU_SAMPLER_MIPMAP = (1 << 1),
|
||||||
GPU_SAMPLER_REPEAT_S = (1 << 2),
|
GPU_SAMPLER_REPEAT_S = (1 << 2),
|
||||||
@@ -52,8 +53,11 @@ typedef enum eGPUSamplerState {
|
|||||||
GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */
|
GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */
|
||||||
GPU_SAMPLER_COMPARE = (1 << 6),
|
GPU_SAMPLER_COMPARE = (1 << 6),
|
||||||
GPU_SAMPLER_ANISO = (1 << 7),
|
GPU_SAMPLER_ANISO = (1 << 7),
|
||||||
|
GPU_SAMPLER_ICON = (1 << 8),
|
||||||
|
|
||||||
|
GPU_SAMPLER_REPEAT = (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R),
|
||||||
/* Don't use that. */
|
/* Don't use that. */
|
||||||
GPU_SAMPLER_MAX = (1 << 8),
|
GPU_SAMPLER_MAX = (GPU_SAMPLER_ICON + 1),
|
||||||
} eGPUSamplerState;
|
} eGPUSamplerState;
|
||||||
|
|
||||||
ENUM_OPERATORS(eGPUSamplerState)
|
ENUM_OPERATORS(eGPUSamplerState)
|
||||||
@@ -62,11 +66,7 @@ ENUM_OPERATORS(eGPUSamplerState)
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GPU_SAMPLER_DEFAULT GPU_SAMPLER_FILTER
|
void GPU_samplers_update(void);
|
||||||
#define GPU_SAMPLER_REPEAT (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R)
|
|
||||||
|
|
||||||
void GPU_samplers_init(void);
|
|
||||||
void GPU_samplers_free(void);
|
|
||||||
|
|
||||||
/* GPU Texture
|
/* GPU Texture
|
||||||
* - always returns unsigned char RGBA textures
|
* - always returns unsigned char RGBA textures
|
||||||
@@ -183,61 +183,40 @@ typedef enum eGPUDataFormat {
|
|||||||
|
|
||||||
unsigned int GPU_texture_memory_usage_get(void);
|
unsigned int GPU_texture_memory_usage_get(void);
|
||||||
|
|
||||||
/* TODO make it static function again. (create function with eGPUDataFormat exposed) */
|
/**
|
||||||
GPUTexture *GPU_texture_create_nD(int w,
|
* \note \a data is expected to be float. If the \a format is not compatible with float data or if
|
||||||
int h,
|
* the data is not in float format, use GPU_texture_update to upload the data with the right data
|
||||||
int d,
|
* format.
|
||||||
int n,
|
* \a mips is the number of mip level to allocate. It must be >= 1.
|
||||||
const void *pixels,
|
*/
|
||||||
eGPUTextureFormat tex_format,
|
GPUTexture *GPU_texture_create_1d(
|
||||||
eGPUDataFormat gpu_data_format,
|
const char *name, int w, int mips, eGPUTextureFormat format, const float *data);
|
||||||
int samples,
|
|
||||||
const bool can_rescale,
|
|
||||||
char err_out[256]);
|
|
||||||
GPUTexture *GPU_texture_cube_create(int w,
|
|
||||||
int d,
|
|
||||||
const void *pixels,
|
|
||||||
eGPUTextureFormat tex_format,
|
|
||||||
eGPUDataFormat gpu_data_format,
|
|
||||||
char err_out[256]);
|
|
||||||
|
|
||||||
GPUTexture *GPU_texture_create_1d(int w,
|
|
||||||
eGPUTextureFormat data_type,
|
|
||||||
const float *pixels,
|
|
||||||
char err_out[256]);
|
|
||||||
GPUTexture *GPU_texture_create_1d_array(
|
GPUTexture *GPU_texture_create_1d_array(
|
||||||
int w, int h, eGPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data);
|
||||||
GPUTexture *GPU_texture_create_2d(
|
GPUTexture *GPU_texture_create_2d(
|
||||||
int w, int h, eGPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data);
|
||||||
GPUTexture *GPU_texture_create_2d_multisample(int w,
|
|
||||||
int h,
|
|
||||||
eGPUTextureFormat data_type,
|
|
||||||
const float *pixels,
|
|
||||||
int samples,
|
|
||||||
char err_out[256]);
|
|
||||||
GPUTexture *GPU_texture_create_2d_array(
|
GPUTexture *GPU_texture_create_2d_array(
|
||||||
int w, int h, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data);
|
||||||
GPUTexture *GPU_texture_create_3d(
|
GPUTexture *GPU_texture_create_3d(
|
||||||
int w, int h, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data);
|
||||||
GPUTexture *GPU_texture_create_cube(int w,
|
GPUTexture *GPU_texture_create_cube(
|
||||||
eGPUTextureFormat data_type,
|
const char *name, int w, int mips, eGPUTextureFormat format, const float *data);
|
||||||
const float *pixels,
|
|
||||||
char err_out[256]);
|
|
||||||
GPUTexture *GPU_texture_create_cube_array(
|
GPUTexture *GPU_texture_create_cube_array(
|
||||||
int w, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]);
|
const char *name, int w, int d, int mips, eGPUTextureFormat format, const float *data);
|
||||||
|
|
||||||
GPUTexture *GPU_texture_create_from_vertbuf(struct GPUVertBuf *vert);
|
|
||||||
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat data_type, const uint buffer);
|
|
||||||
|
|
||||||
GPUTexture *GPU_texture_create_compressed(
|
|
||||||
int w, int h, int miplen, eGPUTextureFormat format, const void *data);
|
|
||||||
|
|
||||||
|
/* Special textures. */
|
||||||
|
GPUTexture *GPU_texture_create_from_vertbuf(const char *name, struct GPUVertBuf *vert);
|
||||||
|
/**
|
||||||
|
* \a data should hold all the data for all mipmaps.
|
||||||
|
*/
|
||||||
|
GPUTexture *GPU_texture_create_compressed_2d(
|
||||||
|
const char *name, int w, int h, int miplen, eGPUTextureFormat format, const void *data);
|
||||||
GPUTexture *GPU_texture_create_error(int dimension, bool array);
|
GPUTexture *GPU_texture_create_error(int dimension, bool array);
|
||||||
|
|
||||||
void GPU_texture_add_mipmap(GPUTexture *tex,
|
void GPU_texture_update_mipmap(GPUTexture *tex,
|
||||||
eGPUDataFormat gpu_data_format,
|
int miplvl,
|
||||||
int miplvl,
|
eGPUDataFormat gpu_data_format,
|
||||||
const void *pixels);
|
const void *pixels);
|
||||||
|
|
||||||
void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *pixels);
|
void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *pixels);
|
||||||
void GPU_texture_update_sub(GPUTexture *tex,
|
void GPU_texture_update_sub(GPUTexture *tex,
|
||||||
@@ -275,18 +254,12 @@ void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter);
|
|||||||
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp);
|
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp);
|
||||||
void GPU_texture_swizzle_set(GPUTexture *tex, const char swizzle[4]);
|
void GPU_texture_swizzle_set(GPUTexture *tex, const char swizzle[4]);
|
||||||
|
|
||||||
/* TODO should be private internal functions. */
|
|
||||||
void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
|
|
||||||
void GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb);
|
|
||||||
int GPU_texture_framebuffer_attachment_get(GPUTexture *tex, struct GPUFrameBuffer *fb);
|
|
||||||
|
|
||||||
int GPU_texture_target(const GPUTexture *tex);
|
int GPU_texture_target(const GPUTexture *tex);
|
||||||
int GPU_texture_width(const GPUTexture *tex);
|
int GPU_texture_width(const GPUTexture *tex);
|
||||||
int GPU_texture_height(const GPUTexture *tex);
|
int GPU_texture_height(const GPUTexture *tex);
|
||||||
int GPU_texture_orig_width(const GPUTexture *tex);
|
int GPU_texture_orig_width(const GPUTexture *tex);
|
||||||
int GPU_texture_orig_height(const GPUTexture *tex);
|
int GPU_texture_orig_height(const GPUTexture *tex);
|
||||||
void GPU_texture_orig_size_set(GPUTexture *tex, int w, int h);
|
void GPU_texture_orig_size_set(GPUTexture *tex, int w, int h);
|
||||||
int GPU_texture_layers(const GPUTexture *tex);
|
|
||||||
eGPUTextureFormat GPU_texture_format(const GPUTexture *tex);
|
eGPUTextureFormat GPU_texture_format(const GPUTexture *tex);
|
||||||
int GPU_texture_samples(const GPUTexture *tex);
|
int GPU_texture_samples(const GPUTexture *tex);
|
||||||
bool GPU_texture_array(const GPUTexture *tex);
|
bool GPU_texture_array(const GPUTexture *tex);
|
||||||
@@ -298,8 +271,6 @@ int GPU_texture_opengl_bindcode(const GPUTexture *tex);
|
|||||||
|
|
||||||
void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size);
|
void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size);
|
||||||
|
|
||||||
void GPU_sampler_icon_bind(int number);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -34,6 +34,7 @@ class Batch;
|
|||||||
class DrawList;
|
class DrawList;
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
class Shader;
|
class Shader;
|
||||||
|
class Texture;
|
||||||
class UniformBuf;
|
class UniformBuf;
|
||||||
|
|
||||||
class GPUBackend {
|
class GPUBackend {
|
||||||
@@ -42,13 +43,15 @@ class GPUBackend {
|
|||||||
|
|
||||||
static GPUBackend *get(void);
|
static GPUBackend *get(void);
|
||||||
|
|
||||||
|
virtual void samplers_update(void) = 0;
|
||||||
|
|
||||||
virtual GPUContext *context_alloc(void *ghost_window) = 0;
|
virtual GPUContext *context_alloc(void *ghost_window) = 0;
|
||||||
|
|
||||||
virtual Batch *batch_alloc(void) = 0;
|
virtual Batch *batch_alloc(void) = 0;
|
||||||
virtual DrawList *drawlist_alloc(int list_length) = 0;
|
virtual DrawList *drawlist_alloc(int list_length) = 0;
|
||||||
virtual FrameBuffer *framebuffer_alloc(const char *name) = 0;
|
virtual FrameBuffer *framebuffer_alloc(const char *name) = 0;
|
||||||
virtual Shader *shader_alloc(const char *name) = 0;
|
virtual Shader *shader_alloc(const char *name) = 0;
|
||||||
// virtual Texture *texture_alloc(void) = 0;
|
virtual Texture *texture_alloc(const char *name) = 0;
|
||||||
virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0;
|
virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
|
|
||||||
static struct GPUGlobal {
|
static struct GPUGlobal {
|
||||||
GLint maxtexsize;
|
GLint maxtexsize;
|
||||||
|
GLint maxtex3dsize;
|
||||||
GLint maxtexlayers;
|
GLint maxtexlayers;
|
||||||
GLint maxcubemapsize;
|
GLint maxcubemapsize;
|
||||||
GLint maxtextures;
|
GLint maxtextures;
|
||||||
@@ -107,7 +108,7 @@ static void gpu_detect_mip_render_workaround(void)
|
|||||||
float *source_pix = (float *)MEM_callocN(sizeof(float[4][6]) * cube_size * cube_size, __func__);
|
float *source_pix = (float *)MEM_callocN(sizeof(float[4][6]) * cube_size * cube_size, __func__);
|
||||||
float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f};
|
float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f};
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_cube(cube_size, GPU_RGBA16F, source_pix, NULL);
|
GPUTexture *tex = GPU_texture_create_cube(__func__, cube_size, 2, GPU_RGBA16F, source_pix);
|
||||||
MEM_freeN(source_pix);
|
MEM_freeN(source_pix);
|
||||||
|
|
||||||
GPU_texture_bind(tex, 0);
|
GPU_texture_bind(tex, 0);
|
||||||
@@ -137,6 +138,11 @@ int GPU_max_texture_size(void)
|
|||||||
return GG.maxtexsize;
|
return GG.maxtexsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GPU_max_texture_3d_size(void)
|
||||||
|
{
|
||||||
|
return GG.maxtex3dsize;
|
||||||
|
}
|
||||||
|
|
||||||
int GPU_max_texture_layers(void)
|
int GPU_max_texture_layers(void)
|
||||||
{
|
{
|
||||||
return GG.maxtexlayers;
|
return GG.maxtexlayers;
|
||||||
@@ -249,6 +255,7 @@ void gpu_extensions_init(void)
|
|||||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
|
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
|
||||||
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
|
||||||
|
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GG.maxtex3dsize);
|
||||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
|
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
|
||||||
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
|
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
|
||||||
|
|
||||||
@@ -386,13 +393,11 @@ void gpu_extensions_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GPU_invalid_tex_init();
|
GPU_invalid_tex_init();
|
||||||
GPU_samplers_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpu_extensions_exit(void)
|
void gpu_extensions_exit(void)
|
||||||
{
|
{
|
||||||
GPU_invalid_tex_free();
|
GPU_invalid_tex_free();
|
||||||
GPU_samplers_free();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_mem_stats_supported(void)
|
bool GPU_mem_stats_supported(void)
|
||||||
|
@@ -66,10 +66,9 @@ FrameBuffer::FrameBuffer(const char *name)
|
|||||||
|
|
||||||
FrameBuffer::~FrameBuffer()
|
FrameBuffer::~FrameBuffer()
|
||||||
{
|
{
|
||||||
GPUFrameBuffer *gpu_fb = reinterpret_cast<GPUFrameBuffer *>(this);
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(attachments_); i++) {
|
for (int i = 0; i < ARRAY_SIZE(attachments_); i++) {
|
||||||
if (attachments_[i].tex != NULL) {
|
if (attachments_[i].tex != NULL) {
|
||||||
GPU_texture_detach_framebuffer(attachments_[i].tex, gpu_fb);
|
reinterpret_cast<Texture *>(attachments_[i].tex)->detach_from(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,10 +95,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));
|
||||||
@@ -118,14 +114,14 @@ void FrameBuffer::attachment_set(GPUAttachmentType type, const GPUAttachment &ne
|
|||||||
/* Unbind previous and bind new. */
|
/* Unbind previous and bind new. */
|
||||||
/* TODO(fclem) cleanup the casts. */
|
/* TODO(fclem) cleanup the casts. */
|
||||||
if (attachment.tex) {
|
if (attachment.tex) {
|
||||||
GPU_texture_detach_framebuffer(attachment.tex, reinterpret_cast<GPUFrameBuffer *>(this));
|
reinterpret_cast<Texture *>(attachment.tex)->detach_from(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
attachment = new_attachment;
|
attachment = new_attachment;
|
||||||
|
|
||||||
/* Might be null if this is for unbinding. */
|
/* Might be null if this is for unbinding. */
|
||||||
if (attachment.tex) {
|
if (attachment.tex) {
|
||||||
GPU_texture_attach_framebuffer(attachment.tex, reinterpret_cast<GPUFrameBuffer *>(this), type);
|
reinterpret_cast<Texture *>(attachment.tex)->attach_to(this, type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* GPU_ATTACHMENT_NONE */
|
/* GPU_ATTACHMENT_NONE */
|
||||||
@@ -134,42 +130,33 @@ void FrameBuffer::attachment_set(GPUAttachmentType type, const GPUAttachment &ne
|
|||||||
dirty_attachments_ = true;
|
dirty_attachments_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameBuffer::attachment_remove(GPUAttachmentType type)
|
||||||
|
{
|
||||||
|
attachments_[type] = GPU_ATTACHMENT_NONE;
|
||||||
|
dirty_attachments_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
void FrameBuffer::recursive_downsample(int max_lvl,
|
void FrameBuffer::recursive_downsample(int max_lvl,
|
||||||
void (*callback)(void *userData, int level),
|
void (*callback)(void *userData, int level),
|
||||||
void *userData)
|
void *userData)
|
||||||
{
|
{
|
||||||
GPUContext *ctx = GPU_context_active_get();
|
|
||||||
/* Bind to make sure the frame-buffer is up to date. */
|
/* Bind to make sure the frame-buffer is up to date. */
|
||||||
this->bind(true);
|
this->bind(true);
|
||||||
|
|
||||||
if (width_ == 1 && height_ == 1) {
|
/* FIXME(fclem): This assumes all mips are defined which may not be the case. */
|
||||||
return;
|
max_lvl = min_ii(max_lvl, floor(log2(max_ii(width_, height_))));
|
||||||
}
|
|
||||||
/* HACK: Make the frame-buffer appear not bound to avoid assert in GPU_texture_bind. */
|
|
||||||
ctx->active_fb = NULL;
|
|
||||||
|
|
||||||
int levels = floor(log2(max_ii(width_, height_)));
|
for (int mip_lvl = 1; mip_lvl <= max_lvl; mip_lvl++) {
|
||||||
max_lvl = min_ii(max_lvl, levels);
|
|
||||||
|
|
||||||
int current_dim[2] = {width_, height_};
|
|
||||||
int mip_lvl;
|
|
||||||
for (mip_lvl = 1; mip_lvl < max_lvl + 1; mip_lvl++) {
|
|
||||||
/* calculate next viewport size */
|
|
||||||
current_dim[0] = max_ii(current_dim[0] / 2, 1);
|
|
||||||
current_dim[1] = max_ii(current_dim[1] / 2, 1);
|
|
||||||
/* Replace attached mip-level for each attachment. */
|
/* Replace attached mip-level for each attachment. */
|
||||||
for (int att = 0; att < ARRAY_SIZE(attachments_); att++) {
|
for (int att = 0; att < ARRAY_SIZE(attachments_); att++) {
|
||||||
GPUTexture *tex = attachments_[att].tex;
|
Texture *tex = reinterpret_cast<Texture *>(attachments_[att].tex);
|
||||||
if (tex != NULL) {
|
if (tex != NULL) {
|
||||||
/* Some Intel HDXXX have issue with rendering to a mipmap that is below
|
/* Some Intel HDXXX have issue with rendering to a mipmap that is below
|
||||||
* the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case
|
* the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case
|
||||||
* we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */
|
* we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */
|
||||||
int map_lvl = (GPU_mip_render_workaround()) ? mip_lvl : (mip_lvl - 1);
|
int mip_max = (GPU_mip_render_workaround()) ? mip_lvl : (mip_lvl - 1);
|
||||||
/* Restrict fetches only to previous level. */
|
/* Restrict fetches only to previous level. */
|
||||||
GPU_texture_bind(tex, 0);
|
tex->mip_range_set(mip_lvl - 1, mip_max);
|
||||||
glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, mip_lvl - 1);
|
|
||||||
glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, map_lvl);
|
|
||||||
GPU_texture_unbind(tex);
|
|
||||||
/* Bind next level. */
|
/* Bind next level. */
|
||||||
attachments_[att].mip = mip_lvl;
|
attachments_[att].mip = mip_lvl;
|
||||||
}
|
}
|
||||||
@@ -177,25 +164,14 @@ void FrameBuffer::recursive_downsample(int max_lvl,
|
|||||||
/* Update the internal attachments and viewport size. */
|
/* Update the internal attachments and viewport size. */
|
||||||
dirty_attachments_ = true;
|
dirty_attachments_ = true;
|
||||||
this->bind(true);
|
this->bind(true);
|
||||||
/* HACK: Make the frame-buffer appear not bound to avoid assert in GPU_texture_bind. */
|
|
||||||
ctx->active_fb = NULL;
|
|
||||||
|
|
||||||
callback(userData, mip_lvl);
|
callback(userData, mip_lvl);
|
||||||
|
|
||||||
/* This is the last mipmap level. Exit loop without incrementing mip_lvl. */
|
|
||||||
if (current_dim[0] == 1 && current_dim[1] == 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int att = 0; att < ARRAY_SIZE(attachments_); att++) {
|
for (int att = 0; att < ARRAY_SIZE(attachments_); att++) {
|
||||||
if (attachments_[att].tex != NULL) {
|
if (attachments_[att].tex != NULL) {
|
||||||
/* Reset mipmap level range. */
|
/* Reset mipmap level range. */
|
||||||
GPUTexture *tex = attachments_[att].tex;
|
reinterpret_cast<Texture *>(attachments_[att].tex)->mip_range_set(0, max_lvl);
|
||||||
GPU_texture_bind(tex, 0);
|
|
||||||
glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
|
|
||||||
glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, mip_lvl);
|
|
||||||
GPU_texture_unbind(tex);
|
|
||||||
/* Reset base level. NOTE: might not be the one bound at the start of this function. */
|
/* Reset base level. NOTE: might not be the one bound at the start of this function. */
|
||||||
attachments_[att].mip = 0;
|
attachments_[att].mip = 0;
|
||||||
}
|
}
|
||||||
@@ -292,7 +268,8 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *gpu_fb, char err_out[256])
|
|||||||
|
|
||||||
void GPU_framebuffer_texture_attach_ex(GPUFrameBuffer *gpu_fb, GPUAttachment attachment, int slot)
|
void GPU_framebuffer_texture_attach_ex(GPUFrameBuffer *gpu_fb, GPUAttachment attachment, int slot)
|
||||||
{
|
{
|
||||||
GPUAttachmentType type = blender::gpu::Texture::attachment_type(attachment.tex, slot);
|
Texture *tex = reinterpret_cast<Texture *>(attachment.tex);
|
||||||
|
GPUAttachmentType type = tex->attachment_type(slot);
|
||||||
reinterpret_cast<FrameBuffer *>(gpu_fb)->attachment_set(type, attachment);
|
reinterpret_cast<FrameBuffer *>(gpu_fb)->attachment_set(type, attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,14 +295,8 @@ void GPU_framebuffer_texture_cubeface_attach(
|
|||||||
|
|
||||||
void GPU_framebuffer_texture_detach(GPUFrameBuffer *gpu_fb, GPUTexture *tex)
|
void GPU_framebuffer_texture_detach(GPUFrameBuffer *gpu_fb, GPUTexture *tex)
|
||||||
{
|
{
|
||||||
GPUAttachment attachment = GPU_ATTACHMENT_NONE;
|
FrameBuffer *fb = reinterpret_cast<FrameBuffer *>(gpu_fb);
|
||||||
int type = GPU_texture_framebuffer_attachment_get(tex, gpu_fb);
|
reinterpret_cast<Texture *>(tex)->detach_from(fb);
|
||||||
if (type != -1) {
|
|
||||||
reinterpret_cast<FrameBuffer *>(gpu_fb)->attachment_set((GPUAttachmentType)type, attachment);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BLI_assert(!"Error: Texture: Framebuffer is not attached");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -605,13 +576,14 @@ GPUOffScreen *GPU_offscreen_create(
|
|||||||
width = max_ii(1, width);
|
width = max_ii(1, width);
|
||||||
|
|
||||||
ofs->color = GPU_texture_create_2d(
|
ofs->color = GPU_texture_create_2d(
|
||||||
width, height, (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, err_out);
|
"ofs_color", width, height, 1, (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL);
|
||||||
|
|
||||||
if (depth) {
|
if (depth) {
|
||||||
ofs->depth = GPU_texture_create_2d(width, height, GPU_DEPTH24_STENCIL8, NULL, err_out);
|
ofs->depth = GPU_texture_create_2d("ofs_depth", width, height, 1, GPU_DEPTH24_STENCIL8, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((depth && !ofs->depth) || !ofs->color) {
|
if ((depth && !ofs->depth) || !ofs->color) {
|
||||||
|
BLI_snprintf(err_out, 256, "GPUTexture: Texture allocation failed.");
|
||||||
GPU_offscreen_free(ofs);
|
GPU_offscreen_free(ofs);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
@@ -131,6 +134,7 @@ class FrameBuffer {
|
|||||||
int dst_offset_y) = 0;
|
int dst_offset_y) = 0;
|
||||||
|
|
||||||
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment);
|
void attachment_set(GPUAttachmentType type, const GPUAttachment &new_attachment);
|
||||||
|
void attachment_remove(GPUAttachmentType type);
|
||||||
|
|
||||||
void recursive_downsample(int max_lvl,
|
void recursive_downsample(int max_lvl,
|
||||||
void (*callback)(void *userData, int level),
|
void (*callback)(void *userData, int level),
|
||||||
|
@@ -157,7 +157,7 @@ static void gpu_material_ramp_texture_build(GPUMaterial *mat)
|
|||||||
GPUColorBandBuilder *builder = mat->coba_builder;
|
GPUColorBandBuilder *builder = mat->coba_builder;
|
||||||
|
|
||||||
mat->coba_tex = GPU_texture_create_1d_array(
|
mat->coba_tex = GPU_texture_create_1d_array(
|
||||||
CM_TABLE + 1, builder->current_layer, GPU_RGBA16F, (float *)builder->pixels, NULL);
|
"mat_ramp", CM_TABLE + 1, builder->current_layer, 1, GPU_RGBA16F, (float *)builder->pixels);
|
||||||
|
|
||||||
MEM_freeN(builder);
|
MEM_freeN(builder);
|
||||||
mat->coba_builder = NULL;
|
mat->coba_builder = NULL;
|
||||||
@@ -546,7 +546,8 @@ struct GPUUniformBuf *GPU_material_sss_profile_get(GPUMaterial *material,
|
|||||||
GPU_texture_free(material->sss_tex_profile);
|
GPU_texture_free(material->sss_tex_profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
material->sss_tex_profile = GPU_texture_create_1d(64, GPU_RGBA16F, translucence_profile, NULL);
|
material->sss_tex_profile = GPU_texture_create_1d(
|
||||||
|
"sss_tex_profile", 64, 1, GPU_RGBA16F, translucence_profile);
|
||||||
|
|
||||||
MEM_freeN(translucence_profile);
|
MEM_freeN(translucence_profile);
|
||||||
|
|
||||||
|
@@ -93,6 +93,11 @@ class ShaderInterface {
|
|||||||
return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, name);
|
return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const ShaderInput *texture_get(const int binding) const
|
||||||
|
{
|
||||||
|
return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, binding);
|
||||||
|
}
|
||||||
|
|
||||||
inline const char *input_name_get(const ShaderInput *input) const
|
inline const char *input_name_get(const ShaderInput *input) const
|
||||||
{
|
{
|
||||||
return name_buffer_ + input->name_offset;
|
return name_buffer_ + input->name_offset;
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include "GPU_state.h"
|
#include "GPU_state.h"
|
||||||
|
|
||||||
|
#include "gpu_texture_private.hh"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace blender {
|
namespace blender {
|
||||||
@@ -160,6 +162,10 @@ class GPUStateManager {
|
|||||||
virtual ~GPUStateManager(){};
|
virtual ~GPUStateManager(){};
|
||||||
|
|
||||||
virtual void apply_state(void) = 0;
|
virtual void apply_state(void) = 0;
|
||||||
|
|
||||||
|
virtual void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) = 0;
|
||||||
|
virtual void texture_unbind(Texture *tex) = 0;
|
||||||
|
virtual void texture_unbind_all(void) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -25,15 +25,203 @@
|
|||||||
|
|
||||||
#include "BLI_assert.h"
|
#include "BLI_assert.h"
|
||||||
|
|
||||||
|
#include "GPU_vertex_buffer.h"
|
||||||
|
|
||||||
|
#include "gpu_framebuffer_private.hh"
|
||||||
|
|
||||||
namespace blender {
|
namespace blender {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
typedef enum eGPUTextureFormatFlag {
|
||||||
|
GPU_FORMAT_DEPTH = (1 << 0),
|
||||||
|
GPU_FORMAT_STENCIL = (1 << 1),
|
||||||
|
GPU_FORMAT_INTEGER = (1 << 2),
|
||||||
|
GPU_FORMAT_FLOAT = (1 << 3),
|
||||||
|
GPU_FORMAT_COMPRESSED = (1 << 4),
|
||||||
|
|
||||||
|
GPU_FORMAT_DEPTH_STENCIL = (GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL),
|
||||||
|
} eGPUTextureFormatFlag;
|
||||||
|
|
||||||
|
ENUM_OPERATORS(eGPUTextureFormatFlag)
|
||||||
|
|
||||||
|
typedef enum eGPUTextureType {
|
||||||
|
GPU_TEXTURE_1D = (1 << 0),
|
||||||
|
GPU_TEXTURE_2D = (1 << 1),
|
||||||
|
GPU_TEXTURE_3D = (1 << 2),
|
||||||
|
GPU_TEXTURE_CUBE = (1 << 3),
|
||||||
|
GPU_TEXTURE_ARRAY = (1 << 4),
|
||||||
|
GPU_TEXTURE_BUFFER = (1 << 5),
|
||||||
|
|
||||||
|
GPU_TEXTURE_1D_ARRAY = (GPU_TEXTURE_1D | GPU_TEXTURE_ARRAY),
|
||||||
|
GPU_TEXTURE_2D_ARRAY = (GPU_TEXTURE_2D | GPU_TEXTURE_ARRAY),
|
||||||
|
GPU_TEXTURE_CUBE_ARRAY = (GPU_TEXTURE_CUBE | GPU_TEXTURE_ARRAY),
|
||||||
|
} eGPUTextureType;
|
||||||
|
|
||||||
|
ENUM_OPERATORS(eGPUTextureType)
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define DEBUG_NAME_LEN 64
|
||||||
|
#else
|
||||||
|
# define DEBUG_NAME_LEN 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum number of FBOs a texture can be attached to. */
|
||||||
|
#define GPU_TEX_MAX_FBO_ATTACHED 13
|
||||||
|
|
||||||
class Texture {
|
class Texture {
|
||||||
public:
|
public:
|
||||||
/** TODO(fclem): make it a non-static function. */
|
/** Internal Sampler state. */
|
||||||
static GPUAttachmentType attachment_type(GPUTexture *tex, int slot)
|
eGPUSamplerState sampler_state = GPU_SAMPLER_DEFAULT;
|
||||||
|
/** Reference counter. */
|
||||||
|
int refcount = 1;
|
||||||
|
/** Width & Height (of source data), optional. */
|
||||||
|
int src_w = 0, src_h = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* ---- Texture format (immutable after init). ---- */
|
||||||
|
/** Width & Height & Depth. For cubemap arrays, d is number of facelayers. */
|
||||||
|
int w_, h_, d_;
|
||||||
|
/** Internal data format. */
|
||||||
|
eGPUTextureFormat format_;
|
||||||
|
/** Format caracteristics. */
|
||||||
|
eGPUTextureFormatFlag format_flag_;
|
||||||
|
/** Texture type. */
|
||||||
|
eGPUTextureType type_;
|
||||||
|
|
||||||
|
/** Number of mipmaps this texture has (Max miplvl). */
|
||||||
|
/* TODO(fclem) Should become immutable and the need for mipmaps should be specified upfront. */
|
||||||
|
int mipmaps_ = -1;
|
||||||
|
/** For error checking */
|
||||||
|
int mip_min_ = 0, mip_max_ = 0;
|
||||||
|
|
||||||
|
/** For debugging */
|
||||||
|
char name_[DEBUG_NAME_LEN];
|
||||||
|
|
||||||
|
/** Framebuffer references to update on deletion. */
|
||||||
|
GPUAttachmentType fb_attachment_[GPU_TEX_MAX_FBO_ATTACHED];
|
||||||
|
FrameBuffer *fb_[GPU_TEX_MAX_FBO_ATTACHED];
|
||||||
|
|
||||||
|
public:
|
||||||
|
Texture(const char *name);
|
||||||
|
virtual ~Texture();
|
||||||
|
|
||||||
|
/* Return true on success. */
|
||||||
|
bool init_1D(int w, int layers, eGPUTextureFormat format);
|
||||||
|
bool init_2D(int w, int h, int layers, eGPUTextureFormat format);
|
||||||
|
bool init_3D(int w, int h, int d, eGPUTextureFormat format);
|
||||||
|
bool init_cubemap(int w, int layers, eGPUTextureFormat format);
|
||||||
|
bool init_buffer(GPUVertBuf *vbo, eGPUTextureFormat format);
|
||||||
|
|
||||||
|
virtual void generate_mipmap(void) = 0;
|
||||||
|
virtual void copy_to(Texture *tex) = 0;
|
||||||
|
virtual void clear(eGPUDataFormat format, const void *data) = 0;
|
||||||
|
virtual void swizzle_set(const char swizzle_mask[4]) = 0;
|
||||||
|
virtual void mip_range_set(int min, int max) = 0;
|
||||||
|
virtual void *read(int mip, eGPUDataFormat format) = 0;
|
||||||
|
|
||||||
|
void attach_to(FrameBuffer *fb, GPUAttachmentType type);
|
||||||
|
void detach_from(FrameBuffer *fb);
|
||||||
|
void update(eGPUDataFormat format, const void *data);
|
||||||
|
|
||||||
|
virtual void update_sub(
|
||||||
|
int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data) = 0;
|
||||||
|
|
||||||
|
/* TODO(fclem) Legacy. Should be removed at some point. */
|
||||||
|
virtual uint gl_bindcode_get(void) const = 0;
|
||||||
|
|
||||||
|
int width_get(void) const
|
||||||
{
|
{
|
||||||
switch (GPU_texture_format(tex)) {
|
return w_;
|
||||||
|
}
|
||||||
|
int height_get(void) const
|
||||||
|
{
|
||||||
|
return h_;
|
||||||
|
}
|
||||||
|
int depth_get(void) const
|
||||||
|
{
|
||||||
|
return d_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mip_size_get(int mip, int r_size[3]) const
|
||||||
|
{
|
||||||
|
/* TODO assert if lvl is below the limit of 1px in each dimension. */
|
||||||
|
int div = 1 << mip;
|
||||||
|
r_size[0] = max_ii(1, w_ / div);
|
||||||
|
|
||||||
|
if (type_ == GPU_TEXTURE_1D_ARRAY) {
|
||||||
|
r_size[1] = h_;
|
||||||
|
}
|
||||||
|
else if (h_ > 0) {
|
||||||
|
r_size[1] = max_ii(1, h_ / div);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_ & (GPU_TEXTURE_ARRAY | GPU_TEXTURE_CUBE)) {
|
||||||
|
r_size[2] = d_;
|
||||||
|
}
|
||||||
|
else if (d_ > 0) {
|
||||||
|
r_size[2] = max_ii(1, d_ / div);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mip_width_get(int mip) const
|
||||||
|
{
|
||||||
|
return max_ii(1, w_ / (1 << mip));
|
||||||
|
}
|
||||||
|
int mip_height_get(int mip) const
|
||||||
|
{
|
||||||
|
return (type_ == GPU_TEXTURE_1D_ARRAY) ? h_ : max_ii(1, h_ / (1 << mip));
|
||||||
|
}
|
||||||
|
int mip_depth_get(int mip) const
|
||||||
|
{
|
||||||
|
return (type_ & (GPU_TEXTURE_ARRAY | GPU_TEXTURE_CUBE)) ? d_ : max_ii(1, d_ / (1 << mip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return number of dimension taking the array type into account. */
|
||||||
|
int dimensions_count(void) const
|
||||||
|
{
|
||||||
|
const int array = (type_ & GPU_TEXTURE_ARRAY) ? 1 : 0;
|
||||||
|
switch (type_ & ~GPU_TEXTURE_ARRAY) {
|
||||||
|
case GPU_TEXTURE_BUFFER:
|
||||||
|
return 1;
|
||||||
|
case GPU_TEXTURE_1D:
|
||||||
|
return 1 + array;
|
||||||
|
case GPU_TEXTURE_2D:
|
||||||
|
return 2 + array;
|
||||||
|
case GPU_TEXTURE_CUBE:
|
||||||
|
case GPU_TEXTURE_3D:
|
||||||
|
default:
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Return number of array layer (or face layer) for texture array or 1 for the others. */
|
||||||
|
int layer_count(void) const
|
||||||
|
{
|
||||||
|
switch (type_) {
|
||||||
|
case GPU_TEXTURE_1D_ARRAY:
|
||||||
|
return h_;
|
||||||
|
case GPU_TEXTURE_2D_ARRAY:
|
||||||
|
case GPU_TEXTURE_CUBE_ARRAY:
|
||||||
|
return d_;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eGPUTextureFormat format_get(void) const
|
||||||
|
{
|
||||||
|
return format_;
|
||||||
|
}
|
||||||
|
eGPUTextureFormatFlag format_flag_get(void) const
|
||||||
|
{
|
||||||
|
return format_flag_;
|
||||||
|
}
|
||||||
|
eGPUTextureType type_get(void) const
|
||||||
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
GPUAttachmentType attachment_type(int slot) const
|
||||||
|
{
|
||||||
|
switch (format_) {
|
||||||
case GPU_DEPTH_COMPONENT32F:
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
case GPU_DEPTH_COMPONENT24:
|
case GPU_DEPTH_COMPONENT24:
|
||||||
case GPU_DEPTH_COMPONENT16:
|
case GPU_DEPTH_COMPONENT16:
|
||||||
@@ -44,10 +232,313 @@ class Texture {
|
|||||||
BLI_assert(slot == 0);
|
BLI_assert(slot == 0);
|
||||||
return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
|
return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
|
||||||
default:
|
default:
|
||||||
return static_cast<GPUAttachmentType>(GPU_FB_COLOR_ATTACHMENT0 + slot);
|
return GPU_FB_COLOR_ATTACHMENT0 + slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool init_internal(void) = 0;
|
||||||
|
virtual bool init_internal(GPUVertBuf *vbo) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef DEBUG_NAME_LEN
|
||||||
|
|
||||||
|
inline size_t to_bytesize(eGPUTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case GPU_RGBA32F:
|
||||||
|
return 32;
|
||||||
|
case GPU_RG32F:
|
||||||
|
case GPU_RGBA16F:
|
||||||
|
case GPU_RGBA16:
|
||||||
|
return 16;
|
||||||
|
case GPU_RGB16F:
|
||||||
|
return 12;
|
||||||
|
case GPU_DEPTH32F_STENCIL8: /* 32-bit depth, 8 bits stencil, and 24 unused bits. */
|
||||||
|
return 8;
|
||||||
|
case GPU_RG16F:
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_RG16:
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
case GPU_RGBA8:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
case GPU_R32F:
|
||||||
|
case GPU_R32UI:
|
||||||
|
case GPU_R32I:
|
||||||
|
return 4;
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
return 3;
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
case GPU_R16F:
|
||||||
|
case GPU_R16UI:
|
||||||
|
case GPU_R16I:
|
||||||
|
case GPU_RG8:
|
||||||
|
case GPU_R16:
|
||||||
|
return 2;
|
||||||
|
case GPU_R8:
|
||||||
|
case GPU_R8UI:
|
||||||
|
return 1;
|
||||||
|
case GPU_SRGB8_A8_DXT1:
|
||||||
|
case GPU_SRGB8_A8_DXT3:
|
||||||
|
case GPU_SRGB8_A8_DXT5:
|
||||||
|
case GPU_RGBA8_DXT1:
|
||||||
|
case GPU_RGBA8_DXT3:
|
||||||
|
case GPU_RGBA8_DXT5:
|
||||||
|
return 1; /* Incorrect but actual size is fractional. */
|
||||||
|
default:
|
||||||
|
BLI_assert(!"Texture format incorrect or unsupported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t to_block_size(eGPUTextureFormat data_type)
|
||||||
|
{
|
||||||
|
switch (data_type) {
|
||||||
|
case GPU_SRGB8_A8_DXT1:
|
||||||
|
case GPU_RGBA8_DXT1:
|
||||||
|
return 8;
|
||||||
|
case GPU_SRGB8_A8_DXT3:
|
||||||
|
case GPU_SRGB8_A8_DXT5:
|
||||||
|
case GPU_RGBA8_DXT3:
|
||||||
|
case GPU_RGBA8_DXT5:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
BLI_assert(!"Texture format is not a compressed format\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline eGPUTextureFormatFlag to_format_flag(eGPUTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
return GPU_FORMAT_DEPTH;
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return GPU_FORMAT_DEPTH_STENCIL;
|
||||||
|
case GPU_R8UI:
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_R16I:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_R16UI:
|
||||||
|
case GPU_R32UI:
|
||||||
|
return GPU_FORMAT_INTEGER;
|
||||||
|
case GPU_SRGB8_A8_DXT1:
|
||||||
|
case GPU_SRGB8_A8_DXT3:
|
||||||
|
case GPU_SRGB8_A8_DXT5:
|
||||||
|
case GPU_RGBA8_DXT1:
|
||||||
|
case GPU_RGBA8_DXT3:
|
||||||
|
case GPU_RGBA8_DXT5:
|
||||||
|
return GPU_FORMAT_COMPRESSED;
|
||||||
|
default:
|
||||||
|
return GPU_FORMAT_FLOAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int to_component_len(eGPUTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case GPU_RGBA8:
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
case GPU_RGBA16F:
|
||||||
|
case GPU_RGBA16:
|
||||||
|
case GPU_RGBA32F:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
return 4;
|
||||||
|
case GPU_RGB16F:
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
return 3;
|
||||||
|
case GPU_RG8:
|
||||||
|
case GPU_RG16:
|
||||||
|
case GPU_RG16F:
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_RG32F:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t to_bytesize(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
|
||||||
|
{
|
||||||
|
switch (data_format) {
|
||||||
|
case GPU_DATA_UNSIGNED_BYTE:
|
||||||
|
return 1 * to_component_len(tex_format);
|
||||||
|
case GPU_DATA_FLOAT:
|
||||||
|
case GPU_DATA_INT:
|
||||||
|
case GPU_DATA_UNSIGNED_INT:
|
||||||
|
return 4 * to_component_len(tex_format);
|
||||||
|
case GPU_DATA_UNSIGNED_INT_24_8:
|
||||||
|
case GPU_DATA_10_11_11_REV:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
BLI_assert(!"Data format incorrect or unsupported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Definitely not complete, edit according to the gl specification. */
|
||||||
|
inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
|
||||||
|
{
|
||||||
|
switch (tex_format) {
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
return data_format == GPU_DATA_FLOAT;
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return data_format == GPU_DATA_UNSIGNED_INT_24_8;
|
||||||
|
case GPU_R8UI:
|
||||||
|
case GPU_R16UI:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_R32UI:
|
||||||
|
return data_format == GPU_DATA_UNSIGNED_INT;
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_R16I:
|
||||||
|
return data_format == GPU_DATA_INT;
|
||||||
|
case GPU_R8:
|
||||||
|
case GPU_RG8:
|
||||||
|
case GPU_RGBA8:
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
return ELEM(data_format, GPU_DATA_UNSIGNED_BYTE, GPU_DATA_FLOAT);
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
return ELEM(data_format, GPU_DATA_10_11_11_REV, GPU_DATA_FLOAT);
|
||||||
|
default:
|
||||||
|
return data_format == GPU_DATA_FLOAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Definitely not complete, edit according to the gl specification. */
|
||||||
|
inline eGPUDataFormat to_data_format(eGPUTextureFormat tex_format)
|
||||||
|
{
|
||||||
|
switch (tex_format) {
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
return GPU_DATA_FLOAT;
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return GPU_DATA_UNSIGNED_INT_24_8;
|
||||||
|
case GPU_R8UI:
|
||||||
|
case GPU_R16UI:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_R32UI:
|
||||||
|
return GPU_DATA_UNSIGNED_INT;
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_R16I:
|
||||||
|
return GPU_DATA_INT;
|
||||||
|
case GPU_R8:
|
||||||
|
case GPU_RG8:
|
||||||
|
case GPU_RGBA8:
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
return GPU_DATA_UNSIGNED_BYTE;
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
return GPU_DATA_10_11_11_REV;
|
||||||
|
default:
|
||||||
|
return GPU_DATA_FLOAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline eGPUFrameBufferBits to_framebuffer_bits(eGPUTextureFormat tex_format)
|
||||||
|
{
|
||||||
|
switch (tex_format) {
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
return GPU_DEPTH_BIT;
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return GPU_DEPTH_BIT | GPU_STENCIL_BIT;
|
||||||
|
default:
|
||||||
|
return GPU_COLOR_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format)
|
||||||
|
{
|
||||||
|
if (format->attr_len > 1 || format->attr_len == 0) {
|
||||||
|
BLI_assert(!"Incorrect vertex format for buffer texture");
|
||||||
|
return GPU_DEPTH_COMPONENT24;
|
||||||
|
}
|
||||||
|
switch (format->attrs[0].comp_len) {
|
||||||
|
case 1:
|
||||||
|
switch (format->attrs[0].comp_type) {
|
||||||
|
case GPU_COMP_I8:
|
||||||
|
return GPU_R8I;
|
||||||
|
case GPU_COMP_U8:
|
||||||
|
return GPU_R8UI;
|
||||||
|
case GPU_COMP_I16:
|
||||||
|
return GPU_R16I;
|
||||||
|
case GPU_COMP_U16:
|
||||||
|
return GPU_R16UI;
|
||||||
|
case GPU_COMP_I32:
|
||||||
|
return GPU_R32I;
|
||||||
|
case GPU_COMP_U32:
|
||||||
|
return GPU_R32UI;
|
||||||
|
case GPU_COMP_F32:
|
||||||
|
return GPU_R32F;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (format->attrs[0].comp_type) {
|
||||||
|
case GPU_COMP_I8:
|
||||||
|
return GPU_RG8I;
|
||||||
|
case GPU_COMP_U8:
|
||||||
|
return GPU_RG8UI;
|
||||||
|
case GPU_COMP_I16:
|
||||||
|
return GPU_RG16I;
|
||||||
|
case GPU_COMP_U16:
|
||||||
|
return GPU_RG16UI;
|
||||||
|
case GPU_COMP_I32:
|
||||||
|
return GPU_RG32I;
|
||||||
|
case GPU_COMP_U32:
|
||||||
|
return GPU_RG32UI;
|
||||||
|
case GPU_COMP_F32:
|
||||||
|
return GPU_RG32F;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* Not supported until GL 4.0 */
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
switch (format->attrs[0].comp_type) {
|
||||||
|
case GPU_COMP_I8:
|
||||||
|
return GPU_RGBA8I;
|
||||||
|
case GPU_COMP_U8:
|
||||||
|
return GPU_RGBA8UI;
|
||||||
|
case GPU_COMP_I16:
|
||||||
|
return GPU_RGBA16I;
|
||||||
|
case GPU_COMP_U16:
|
||||||
|
return GPU_RGBA16UI;
|
||||||
|
case GPU_COMP_I32:
|
||||||
|
return GPU_RGBA32I;
|
||||||
|
case GPU_COMP_U32:
|
||||||
|
return GPU_RGBA32UI;
|
||||||
|
case GPU_COMP_F32:
|
||||||
|
return GPU_RGBA32F;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BLI_assert(!"Unsupported vertex format for buffer texture");
|
||||||
|
return GPU_DEPTH_COMPONENT24;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
} // namespace blender
|
} // namespace blender
|
||||||
|
@@ -380,7 +380,7 @@ GPUTexture *GPU_viewport_texture_pool_query(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tex = GPU_texture_create_2d(width, height, format, NULL, NULL);
|
tex = GPU_texture_create_2d("temp_from_pool", width, height, 1, format, NULL);
|
||||||
/* Doing filtering for depth does not make sense when not doing shadow mapping,
|
/* Doing filtering for depth does not make sense when not doing shadow mapping,
|
||||||
* and enabling texture filtering on integer texture make them unreadable. */
|
* and enabling texture filtering on integer texture make them unreadable. */
|
||||||
bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
|
bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
|
||||||
@@ -453,16 +453,21 @@ static void gpu_viewport_default_fb_create(GPUViewport *viewport)
|
|||||||
int *size = viewport->size;
|
int *size = viewport->size;
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL);
|
dtxl->color = GPU_texture_create_2d("dtxl_color", UNPACK2(size), 1, GPU_RGBA16F, NULL);
|
||||||
dtxl->color_overlay = GPU_texture_create_2d(size[0], size[1], GPU_SRGB8_A8, NULL, NULL);
|
dtxl->color_overlay = GPU_texture_create_2d(
|
||||||
if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
|
"dtxl_color_overlay", UNPACK2(size), 1, GPU_SRGB8_A8, NULL);
|
||||||
dtxl->color_stereo = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL);
|
|
||||||
dtxl->color_overlay_stereo = GPU_texture_create_2d(size[0], size[1], GPU_SRGB8_A8, NULL, NULL);
|
if (viewport->flag & GPU_VIEWPORT_STEREO) {
|
||||||
|
dtxl->color_stereo = GPU_texture_create_2d(
|
||||||
|
"dtxl_color_stereo", UNPACK2(size), 1, GPU_RGBA16F, NULL);
|
||||||
|
dtxl->color_overlay_stereo = GPU_texture_create_2d(
|
||||||
|
"dtxl_color_overlay_stereo", UNPACK2(size), 1, GPU_SRGB8_A8, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can be shared with GPUOffscreen. */
|
/* Can be shared with GPUOffscreen. */
|
||||||
if (dtxl->depth == NULL) {
|
if (dtxl->depth == NULL) {
|
||||||
dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL);
|
dtxl->depth = GPU_texture_create_2d(
|
||||||
|
"dtxl_depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dtxl->depth || !dtxl->color) {
|
if (!dtxl->depth || !dtxl->color) {
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "gl_drawlist.hh"
|
#include "gl_drawlist.hh"
|
||||||
#include "gl_framebuffer.hh"
|
#include "gl_framebuffer.hh"
|
||||||
#include "gl_shader.hh"
|
#include "gl_shader.hh"
|
||||||
|
#include "gl_texture.hh"
|
||||||
#include "gl_uniform_buffer.hh"
|
#include "gl_uniform_buffer.hh"
|
||||||
|
|
||||||
namespace blender {
|
namespace blender {
|
||||||
@@ -42,11 +43,25 @@ class GLBackend : public GPUBackend {
|
|||||||
GLSharedOrphanLists shared_orphan_list_;
|
GLSharedOrphanLists shared_orphan_list_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
GLBackend()
|
||||||
|
{
|
||||||
|
GLTexture::samplers_init();
|
||||||
|
}
|
||||||
|
~GLBackend()
|
||||||
|
{
|
||||||
|
GLTexture::samplers_free();
|
||||||
|
}
|
||||||
|
|
||||||
static GLBackend *get(void)
|
static GLBackend *get(void)
|
||||||
{
|
{
|
||||||
return static_cast<GLBackend *>(GPUBackend::get());
|
return static_cast<GLBackend *>(GPUBackend::get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void samplers_update(void) override
|
||||||
|
{
|
||||||
|
GLTexture::samplers_update();
|
||||||
|
};
|
||||||
|
|
||||||
GPUContext *context_alloc(void *ghost_window)
|
GPUContext *context_alloc(void *ghost_window)
|
||||||
{
|
{
|
||||||
return new GLContext(ghost_window, shared_orphan_list_);
|
return new GLContext(ghost_window, shared_orphan_list_);
|
||||||
@@ -72,6 +87,11 @@ class GLBackend : public GPUBackend {
|
|||||||
return new GLShader(name);
|
return new GLShader(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Texture *texture_alloc(const char *name)
|
||||||
|
{
|
||||||
|
return new GLTexture(name);
|
||||||
|
};
|
||||||
|
|
||||||
UniformBuf *uniformbuf_alloc(int size, const char *name)
|
UniformBuf *uniformbuf_alloc(int size, const char *name)
|
||||||
{
|
{
|
||||||
return new GLUniformBuf(size, name);
|
return new GLUniformBuf(size, name);
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
#include "BLI_set.hh"
|
#include "BLI_set.hh"
|
||||||
#include "BLI_vector.hh"
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
|
#include "gl_state.hh"
|
||||||
|
|
||||||
#include "glew-mx.h"
|
#include "glew-mx.h"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -83,6 +85,12 @@ class GLContext : public GPUContext {
|
|||||||
void activate(void) override;
|
void activate(void) override;
|
||||||
void deactivate(void) override;
|
void deactivate(void) override;
|
||||||
|
|
||||||
|
static inline GLStateManager *state_manager_active_get()
|
||||||
|
{
|
||||||
|
GLContext *ctx = static_cast<GLContext *>(GPU_context_active_get());
|
||||||
|
return static_cast<GLStateManager *>(ctx->state_manager);
|
||||||
|
};
|
||||||
|
|
||||||
/* TODO(fclem) these needs to become private. */
|
/* TODO(fclem) these needs to become private. */
|
||||||
public:
|
public:
|
||||||
void orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id);
|
void orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id);
|
||||||
|
@@ -28,6 +28,10 @@
|
|||||||
#include "BLI_system.h"
|
#include "BLI_system.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "BKE_global.h"
|
||||||
|
|
||||||
|
#include "GPU_platform.h"
|
||||||
|
|
||||||
#include "glew-mx.h"
|
#include "glew-mx.h"
|
||||||
|
|
||||||
#include "gl_context.hh"
|
#include "gl_context.hh"
|
||||||
@@ -37,6 +41,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Avoid too much NVidia buffer info in the output log. */
|
||||||
|
#define TRIM_NVIDIA_BUFFER_INFO 1
|
||||||
|
|
||||||
namespace blender::gpu::debug {
|
namespace blender::gpu::debug {
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@@ -65,6 +72,13 @@ static void APIENTRY debug_callback(GLenum UNUSED(source),
|
|||||||
{
|
{
|
||||||
const char format[] = "GPUDebug: %s%s\033[0m\n";
|
const char format[] = "GPUDebug: %s%s\033[0m\n";
|
||||||
|
|
||||||
|
if (TRIM_NVIDIA_BUFFER_INFO &&
|
||||||
|
GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) &&
|
||||||
|
STREQLEN("Buffer detailed info", message, 20)) {
|
||||||
|
/** Supress buffer infos flooding the output. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) {
|
if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) {
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
fprintf(stderr, format, "\033[2m", message);
|
fprintf(stderr, format, "\033[2m", message);
|
||||||
@@ -179,6 +193,10 @@ void check_gl_error(const char *info)
|
|||||||
|
|
||||||
void check_gl_resources(const char *info)
|
void check_gl_resources(const char *info)
|
||||||
{
|
{
|
||||||
|
if (!(G.debug & G_DEBUG_GPU)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GLContext *ctx = static_cast<GLContext *>(GPU_context_active_get());
|
GLContext *ctx = static_cast<GLContext *>(GPU_context_active_get());
|
||||||
ShaderInterface *interface = ctx->shader->interface;
|
ShaderInterface *interface = ctx->shader->interface;
|
||||||
/* NOTE: This only check binding. To be valid, the bound ubo needs to
|
/* NOTE: This only check binding. To be valid, the bound ubo needs to
|
||||||
@@ -186,7 +204,12 @@ void check_gl_resources(const char *info)
|
|||||||
uint16_t ubo_needed = interface->enabled_ubo_mask_;
|
uint16_t ubo_needed = interface->enabled_ubo_mask_;
|
||||||
ubo_needed &= ~ctx->bound_ubo_slots;
|
ubo_needed &= ~ctx->bound_ubo_slots;
|
||||||
|
|
||||||
if (ubo_needed == 0) {
|
/* NOTE: This only check binding. To be valid, the bound texture needs to
|
||||||
|
* be the same format/target the shader expects. */
|
||||||
|
uint64_t tex_needed = interface->enabled_tex_mask_;
|
||||||
|
tex_needed &= ~ctx->state_manager_active_get()->bound_texture_slots();
|
||||||
|
|
||||||
|
if (ubo_needed == 0 && tex_needed == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +223,22 @@ void check_gl_resources(const char *info)
|
|||||||
debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
|
debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; tex_needed != 0; i++, tex_needed >>= 1) {
|
||||||
|
if ((tex_needed & 1) != 0) {
|
||||||
|
const ShaderInput *tex_input = interface->texture_get(i);
|
||||||
|
const char *tex_name = interface->input_name_get(tex_input);
|
||||||
|
const char *sh_name = ctx->shader->name_get();
|
||||||
|
char msg[256];
|
||||||
|
SNPRINTF(msg, "Missing Texture bind at slot %d : %s > %s : %s", i, sh_name, tex_name, info);
|
||||||
|
debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void raise_gl_error(const char *msg)
|
||||||
|
{
|
||||||
|
debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@@ -37,6 +37,7 @@ namespace debug {
|
|||||||
# define GL_CHECK_RESOURCES(info)
|
# define GL_CHECK_RESOURCES(info)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void raise_gl_error(const char *info);
|
||||||
void check_gl_error(const char *info);
|
void check_gl_error(const char *info);
|
||||||
void check_gl_resources(const char *info);
|
void check_gl_resources(const char *info);
|
||||||
void init_gl_callbacks(void);
|
void init_gl_callbacks(void);
|
||||||
|
@@ -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,
|
||||||
|
@@ -39,6 +39,9 @@ class GLStateManager;
|
|||||||
* Implementation of FrameBuffer object using OpenGL.
|
* Implementation of FrameBuffer object using OpenGL.
|
||||||
**/
|
**/
|
||||||
class GLFrameBuffer : public FrameBuffer {
|
class GLFrameBuffer : public FrameBuffer {
|
||||||
|
/* For debugging purpose. */
|
||||||
|
friend class GLTexture;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** OpenGL handle. */
|
/** OpenGL handle. */
|
||||||
GLuint fbo_id_ = 0;
|
GLuint fbo_id_ = 0;
|
||||||
@@ -81,6 +84,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,
|
||||||
|
@@ -20,7 +20,10 @@
|
|||||||
* \ingroup gpu
|
* \ingroup gpu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "BKE_global.h"
|
||||||
|
|
||||||
#include "BLI_math_base.h"
|
#include "BLI_math_base.h"
|
||||||
|
#include "BLI_math_bits.h"
|
||||||
|
|
||||||
#include "GPU_extensions.h"
|
#include "GPU_extensions.h"
|
||||||
|
|
||||||
@@ -28,9 +31,11 @@
|
|||||||
|
|
||||||
#include "gl_context.hh"
|
#include "gl_context.hh"
|
||||||
#include "gl_framebuffer.hh"
|
#include "gl_framebuffer.hh"
|
||||||
|
#include "gl_texture.hh"
|
||||||
|
|
||||||
#include "gl_state.hh"
|
#include "gl_state.hh"
|
||||||
|
|
||||||
using namespace blender::gpu;
|
namespace blender::gpu {
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name GLStateManager
|
/** \name GLStateManager
|
||||||
@@ -69,6 +74,7 @@ void GLStateManager::apply_state(void)
|
|||||||
{
|
{
|
||||||
this->set_state(this->state);
|
this->set_state(this->state);
|
||||||
this->set_mutable_state(this->mutable_state);
|
this->set_mutable_state(this->mutable_state);
|
||||||
|
this->texture_bind_apply();
|
||||||
active_fb->apply_state();
|
active_fb->apply_state();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -419,3 +425,111 @@ void GLStateManager::set_blend(const eGPUBlend value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Texture state managment
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
void GLStateManager::texture_bind(Texture *tex_, eGPUSamplerState sampler_type, int unit)
|
||||||
|
{
|
||||||
|
BLI_assert(unit < GPU_max_textures());
|
||||||
|
GLTexture *tex = static_cast<GLTexture *>(tex_);
|
||||||
|
if (G.debug & G_DEBUG_GPU) {
|
||||||
|
tex->check_feedback_loop();
|
||||||
|
}
|
||||||
|
/* Eliminate redundant binds. */
|
||||||
|
if ((textures_[unit] == tex->tex_id_) &&
|
||||||
|
(samplers_[unit] == GLTexture::samplers_[sampler_type])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
targets_[unit] = tex->target_;
|
||||||
|
textures_[unit] = tex->tex_id_;
|
||||||
|
samplers_[unit] = GLTexture::samplers_[sampler_type];
|
||||||
|
tex->is_bound_ = true;
|
||||||
|
dirty_texture_binds_ |= 1 << unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bind the texture to slot 0 for editing purpose. Used by legacy pipeline. */
|
||||||
|
void GLStateManager::texture_bind_temp(GLTexture *tex)
|
||||||
|
{
|
||||||
|
// BLI_assert(!GLEW_ARB_direct_state_access);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(tex->target_, tex->tex_id_);
|
||||||
|
/* Will reset the first texture that was originaly bound to slot 0 back before drawing. */
|
||||||
|
dirty_texture_binds_ |= 1;
|
||||||
|
/* NOTE: This might leave this texture attached to this target even after update.
|
||||||
|
* In practice it is not causing problems as we have incorrect binding detection
|
||||||
|
* at higher level. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLStateManager::texture_unbind(Texture *tex_)
|
||||||
|
{
|
||||||
|
GLTexture *tex = static_cast<GLTexture *>(tex_);
|
||||||
|
if (!tex->is_bound_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint tex_id = tex->tex_id_;
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(textures_); i++) {
|
||||||
|
if (textures_[i] == tex_id) {
|
||||||
|
textures_[i] = 0;
|
||||||
|
samplers_[i] = 0;
|
||||||
|
dirty_texture_binds_ |= 1 << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tex->is_bound_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLStateManager::texture_unbind_all(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(textures_); i++) {
|
||||||
|
if (textures_[i] != 0) {
|
||||||
|
textures_[i] = 0;
|
||||||
|
samplers_[i] = 0;
|
||||||
|
dirty_texture_binds_ |= 1 << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->texture_bind_apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLStateManager::texture_bind_apply(void)
|
||||||
|
{
|
||||||
|
if (dirty_texture_binds_ == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint64_t dirty_bind = dirty_texture_binds_;
|
||||||
|
dirty_texture_binds_ = 0;
|
||||||
|
|
||||||
|
int first = bitscan_forward_uint64(dirty_bind);
|
||||||
|
int last = 64 - bitscan_reverse_uint64(dirty_bind);
|
||||||
|
int count = last - first;
|
||||||
|
|
||||||
|
if (GLEW_ARB_multi_bind) {
|
||||||
|
glBindTextures(first, count, textures_ + first);
|
||||||
|
glBindSamplers(first, count, samplers_ + first);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int unit = first; unit < last; unit++) {
|
||||||
|
if ((dirty_bind >> unit) & 1UL) {
|
||||||
|
glActiveTexture(GL_TEXTURE0 + unit);
|
||||||
|
glBindTexture(targets_[unit], textures_[unit]);
|
||||||
|
glBindSampler(unit, samplers_[unit]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GLStateManager::bound_texture_slots(void)
|
||||||
|
{
|
||||||
|
uint64_t bound_slots = 0;
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(textures_); i++) {
|
||||||
|
if (textures_[i] != 0) {
|
||||||
|
bound_slots |= 1 << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bound_slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
} // namespace blender::gpu
|
@@ -20,6 +20,8 @@
|
|||||||
* \ingroup gpu
|
* \ingroup gpu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
@@ -32,6 +34,7 @@ namespace blender {
|
|||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
class GLFrameBuffer;
|
class GLFrameBuffer;
|
||||||
|
class GLTexture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State manager keeping track of the draw state and applying it before drawing.
|
* State manager keeping track of the draw state and applying it before drawing.
|
||||||
@@ -49,11 +52,30 @@ class GLStateManager : public GPUStateManager {
|
|||||||
/** Limits. */
|
/** Limits. */
|
||||||
float line_width_range_[2];
|
float line_width_range_[2];
|
||||||
|
|
||||||
|
/** Texture state:
|
||||||
|
* We keep the full stack of textures and sampler bounds to use multi bind, and to be able to
|
||||||
|
* edit and restore texture binds on the fly without querying the context.
|
||||||
|
* Also this allows us to keep track of textures bounds to many texture units.
|
||||||
|
* Keep the targets to know what target to set to 0 for unbinding (legacy).
|
||||||
|
* Init first target to GL_TEXTURE_2D for texture_bind_temp to work.
|
||||||
|
*/
|
||||||
|
GLuint targets_[64] = {GL_TEXTURE_2D};
|
||||||
|
GLuint textures_[64] = {0};
|
||||||
|
GLuint samplers_[64] = {0};
|
||||||
|
uint64_t dirty_texture_binds_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLStateManager();
|
GLStateManager();
|
||||||
|
|
||||||
void apply_state(void) override;
|
void apply_state(void) override;
|
||||||
|
|
||||||
|
void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) override;
|
||||||
|
void texture_bind_temp(GLTexture *tex);
|
||||||
|
void texture_unbind(Texture *tex) override;
|
||||||
|
void texture_unbind_all(void) override;
|
||||||
|
|
||||||
|
uint64_t bound_texture_slots(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void set_write_mask(const eGPUWriteMask value);
|
static void set_write_mask(const eGPUWriteMask value);
|
||||||
static void set_depth_test(const eGPUDepthTest value);
|
static void set_depth_test(const eGPUDepthTest value);
|
||||||
@@ -70,6 +92,8 @@ class GLStateManager : public GPUStateManager {
|
|||||||
void set_state(const GPUState &state);
|
void set_state(const GPUState &state);
|
||||||
void set_mutable_state(const GPUStateMutable &state);
|
void set_mutable_state(const GPUStateMutable &state);
|
||||||
|
|
||||||
|
void texture_bind_apply(void);
|
||||||
|
|
||||||
MEM_CXX_CLASS_ALLOC_FUNCS("GLStateManager")
|
MEM_CXX_CLASS_ALLOC_FUNCS("GLStateManager")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
689
source/blender/gpu/opengl/gl_texture.cc
Normal file
689
source/blender/gpu/opengl/gl_texture.cc
Normal file
@@ -0,0 +1,689 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2020 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup gpu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BKE_global.h"
|
||||||
|
|
||||||
|
#include "DNA_userdef_types.h"
|
||||||
|
|
||||||
|
#include "GPU_extensions.h"
|
||||||
|
#include "GPU_framebuffer.h"
|
||||||
|
#include "GPU_platform.h"
|
||||||
|
|
||||||
|
#include "gl_backend.hh"
|
||||||
|
#include "gl_debug.hh"
|
||||||
|
#include "gl_state.hh"
|
||||||
|
|
||||||
|
#include "gl_texture.hh"
|
||||||
|
|
||||||
|
namespace blender::gpu {
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Creation & Deletion
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
GLTexture::GLTexture(const char *name) : Texture(name)
|
||||||
|
{
|
||||||
|
BLI_assert(GPU_context_active_get() != NULL);
|
||||||
|
|
||||||
|
glGenTextures(1, &tex_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexture::~GLTexture()
|
||||||
|
{
|
||||||
|
if (framebuffer_) {
|
||||||
|
GPU_framebuffer_free(framebuffer_);
|
||||||
|
}
|
||||||
|
GPUContext *ctx = GPU_context_active_get();
|
||||||
|
if (ctx != NULL && is_bound_) {
|
||||||
|
/* This avoid errors when the texture is still inside the bound texture array. */
|
||||||
|
ctx->state_manager->texture_unbind(this);
|
||||||
|
}
|
||||||
|
GLBackend::get()->tex_free(tex_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true on success. */
|
||||||
|
bool GLTexture::init_internal(void)
|
||||||
|
{
|
||||||
|
if ((format_ == GPU_DEPTH24_STENCIL8) && GPU_depth_blitting_workaround()) {
|
||||||
|
/* MacOS + Radeon Pro fails to blit depth on GPU_DEPTH24_STENCIL8
|
||||||
|
* but works on GPU_DEPTH32F_STENCIL8. */
|
||||||
|
format_ = GPU_DEPTH32F_STENCIL8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type_ == GPU_TEXTURE_CUBE_ARRAY) && !GPU_arb_texture_cube_map_array_is_supported()) {
|
||||||
|
debug::raise_gl_error("Attempt to create a cubemap array without hardware support!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ = to_gl_target(type_);
|
||||||
|
|
||||||
|
/* We need to bind once to define the texture type. */
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
|
||||||
|
if (!this->proxy_check(0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ensure_mipmaps(0);
|
||||||
|
|
||||||
|
/* Avoid issue with incomplete textures. */
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
glTextureParameteri(tex_id_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
|
||||||
|
char sh_name[64];
|
||||||
|
SNPRINTF(sh_name, "Texture-%s", name_);
|
||||||
|
/* Binding before setting the label is needed on some drivers. */
|
||||||
|
glObjectLabel(GL_TEXTURE, tex_id_, -1, sh_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GL_CHECK_ERROR("Post-texture creation");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true on success. */
|
||||||
|
bool GLTexture::init_internal(GPUVertBuf *vbo)
|
||||||
|
{
|
||||||
|
target_ = to_gl_target(type_);
|
||||||
|
|
||||||
|
/* We need to bind once to define the texture type. */
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
|
||||||
|
GLenum internal_format = to_gl_internal_format(format_);
|
||||||
|
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
glTextureBuffer(tex_id_, internal_format, vbo->vbo_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glTexBuffer(target_, internal_format, vbo->vbo_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
|
||||||
|
char sh_name[64];
|
||||||
|
SNPRINTF(sh_name, "Texture-%s", name_);
|
||||||
|
/* Binding before setting the label is needed on some drivers. */
|
||||||
|
glObjectLabel(GL_TEXTURE, tex_id_, -1, sh_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GL_CHECK_ERROR("Post-texture buffer creation");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Will create enough mipmaps up to get to the given level. */
|
||||||
|
void GLTexture::ensure_mipmaps(int miplvl)
|
||||||
|
{
|
||||||
|
int effective_h = (type_ == GPU_TEXTURE_1D_ARRAY) ? 0 : h_;
|
||||||
|
int effective_d = (type_ != GPU_TEXTURE_3D) ? 0 : d_;
|
||||||
|
int max_dimension = max_iii(w_, effective_h, effective_d);
|
||||||
|
int max_miplvl = floor(log2(max_dimension));
|
||||||
|
miplvl = min_ii(miplvl, max_miplvl);
|
||||||
|
|
||||||
|
while (mipmaps_ < miplvl) {
|
||||||
|
int mip = ++mipmaps_;
|
||||||
|
const int dimensions = this->dimensions_count();
|
||||||
|
|
||||||
|
int w = mip_width_get(mip);
|
||||||
|
int h = mip_height_get(mip);
|
||||||
|
int d = mip_depth_get(mip);
|
||||||
|
GLenum internal_format = to_gl_internal_format(format_);
|
||||||
|
GLenum gl_format = to_gl_data_format(format_);
|
||||||
|
GLenum gl_type = to_gl(to_data_format(format_));
|
||||||
|
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
|
||||||
|
if (type_ == GPU_TEXTURE_CUBE) {
|
||||||
|
for (int i = 0; i < d; i++) {
|
||||||
|
GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
|
||||||
|
glTexImage2D(target, mip, internal_format, w, h, 0, gl_format, gl_type, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (format_flag_ & GPU_FORMAT_COMPRESSED) {
|
||||||
|
size_t size = ((w + 3) / 4) * ((h + 3) / 4) * to_block_size(format_);
|
||||||
|
switch (dimensions) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glCompressedTexImage1D(target_, mip, internal_format, w, 0, size, NULL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glCompressedTexImage2D(target_, mip, internal_format, w, h, 0, size, NULL);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glCompressedTexImage3D(target_, mip, internal_format, w, h, d, 0, size, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (dimensions) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glTexImage1D(target_, mip, internal_format, w, 0, gl_format, gl_type, NULL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glTexImage2D(target_, mip, internal_format, w, h, 0, gl_format, gl_type, NULL);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glTexImage3D(target_, mip, internal_format, w, h, d, 0, gl_format, gl_type, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_CHECK_ERROR("Post-mipmap creation");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mip_range_set(0, mipmaps_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Operations
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
void GLTexture::update_sub_direct_state_access(
|
||||||
|
int mip, int offset[3], int extent[3], GLenum format, GLenum type, const void *data)
|
||||||
|
{
|
||||||
|
if (format_flag_ & GPU_FORMAT_COMPRESSED) {
|
||||||
|
size_t size = ((extent[0] + 3) / 4) * ((extent[1] + 3) / 4) * to_block_size(format_);
|
||||||
|
switch (this->dimensions_count()) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glCompressedTextureSubImage1D(tex_id_, mip, offset[0], extent[0], format, size, data);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glCompressedTextureSubImage2D(
|
||||||
|
tex_id_, mip, UNPACK2(offset), UNPACK2(extent), format, size, data);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glCompressedTextureSubImage3D(
|
||||||
|
tex_id_, mip, UNPACK3(offset), UNPACK3(extent), format, size, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (this->dimensions_count()) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glTextureSubImage1D(tex_id_, mip, offset[0], extent[0], format, type, data);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glTextureSubImage2D(tex_id_, mip, UNPACK2(offset), UNPACK2(extent), format, type, data);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glTextureSubImage3D(tex_id_, mip, UNPACK3(offset), UNPACK3(extent), format, type, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GL_CHECK_ERROR("Post-update_sub_direct_state_access");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::update_sub(
|
||||||
|
int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data)
|
||||||
|
{
|
||||||
|
BLI_assert(validate_data_format(format_, type));
|
||||||
|
BLI_assert(data != NULL);
|
||||||
|
|
||||||
|
this->ensure_mipmaps(mip);
|
||||||
|
|
||||||
|
if (mip > mipmaps_) {
|
||||||
|
debug::raise_gl_error("Updating a miplvl on a texture too small to have this many levels.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int dimensions = this->dimensions_count();
|
||||||
|
GLenum gl_format = to_gl_data_format(format_);
|
||||||
|
GLenum gl_type = to_gl(type);
|
||||||
|
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
this->update_sub_direct_state_access(mip, offset, extent, gl_format, gl_type, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
if (type_ == GPU_TEXTURE_CUBE) {
|
||||||
|
for (int i = 0; i < extent[2]; i++) {
|
||||||
|
GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset[2] + i;
|
||||||
|
glTexSubImage2D(target, mip, UNPACK2(offset), UNPACK2(extent), gl_format, gl_type, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (format_flag_ & GPU_FORMAT_COMPRESSED) {
|
||||||
|
size_t size = ((extent[0] + 3) / 4) * ((extent[1] + 3) / 4) * to_block_size(format_);
|
||||||
|
switch (dimensions) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glCompressedTexSubImage1D(target_, mip, offset[0], extent[0], gl_format, size, data);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glCompressedTexSubImage2D(
|
||||||
|
target_, mip, UNPACK2(offset), UNPACK2(extent), gl_format, size, data);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glCompressedTexSubImage3D(
|
||||||
|
target_, mip, UNPACK3(offset), UNPACK3(extent), gl_format, size, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (dimensions) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glTexSubImage1D(target_, mip, offset[0], extent[0], gl_format, gl_type, data);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glTexSubImage2D(target_, mip, UNPACK2(offset), UNPACK2(extent), gl_format, gl_type, data);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glTexSubImage3D(target_, mip, UNPACK3(offset), UNPACK3(extent), gl_format, gl_type, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_CHECK_ERROR("Post-update_sub");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This will create the mipmap images and populate them with filtered data from base level.
|
||||||
|
* WARNING: Depth textures are not populated but they have their mips correctly defined.
|
||||||
|
* WARNING: This resets the mipmap range.
|
||||||
|
*/
|
||||||
|
void GLTexture::generate_mipmap(void)
|
||||||
|
{
|
||||||
|
this->ensure_mipmaps(9999);
|
||||||
|
/* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789).
|
||||||
|
* In this case we just create a complete texture with mipmaps manually without
|
||||||
|
* down-sampling. You must initialize the texture levels using other methods like
|
||||||
|
* GPU_framebuffer_recursive_downsample(). */
|
||||||
|
if (format_flag_ & GPU_FORMAT_DEPTH) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Downsample from mip 0 using implementation. */
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
glGenerateTextureMipmap(tex_id_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
glGenerateMipmap(target_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::clear(eGPUDataFormat data_format, const void *data)
|
||||||
|
{
|
||||||
|
BLI_assert(validate_data_format(format_, data_format));
|
||||||
|
|
||||||
|
if (GLEW_ARB_clear_texture && !(G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS)) {
|
||||||
|
int mip = 0;
|
||||||
|
GLenum gl_format = to_gl_data_format(format_);
|
||||||
|
GLenum gl_type = to_gl(data_format);
|
||||||
|
glClearTexImage(tex_id_, mip, gl_format, gl_type, data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Fallback for older GL. */
|
||||||
|
GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
|
||||||
|
|
||||||
|
FrameBuffer *fb = reinterpret_cast<FrameBuffer *>(this->framebuffer_get());
|
||||||
|
fb->bind(true);
|
||||||
|
fb->clear_attachment(this->attachment_type(0), data_format, data);
|
||||||
|
|
||||||
|
GPU_framebuffer_bind(prev_fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::copy_to(Texture *dst_)
|
||||||
|
{
|
||||||
|
GLTexture *dst = static_cast<GLTexture *>(dst_);
|
||||||
|
GLTexture *src = this;
|
||||||
|
|
||||||
|
BLI_assert((dst->w_ == src->w_) && (dst->h_ == src->h_) && (dst->d_ == src->d_));
|
||||||
|
BLI_assert(dst->format_ == src->format_);
|
||||||
|
BLI_assert(dst->type_ == src->type_);
|
||||||
|
/* TODO support array / 3D textures. */
|
||||||
|
BLI_assert(dst->d_ == 0);
|
||||||
|
|
||||||
|
if (GLEW_ARB_copy_image && !GPU_texture_copy_workaround()) {
|
||||||
|
/* Opengl 4.3 */
|
||||||
|
int mip = 0;
|
||||||
|
/* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
|
||||||
|
int extent[3] = {1, 1, 1};
|
||||||
|
this->mip_size_get(mip, extent);
|
||||||
|
glCopyImageSubData(
|
||||||
|
src->tex_id_, target_, mip, 0, 0, 0, dst->tex_id_, target_, mip, 0, 0, 0, UNPACK3(extent));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Fallback for older GL. */
|
||||||
|
GPU_framebuffer_blit(
|
||||||
|
src->framebuffer_get(), 0, dst->framebuffer_get(), 0, to_framebuffer_bits(format_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *GLTexture::read(int mip, eGPUDataFormat type)
|
||||||
|
{
|
||||||
|
BLI_assert(!(format_flag_ & GPU_FORMAT_COMPRESSED));
|
||||||
|
BLI_assert(mip <= mipmaps_);
|
||||||
|
BLI_assert(validate_data_format(format_, type));
|
||||||
|
|
||||||
|
/* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
|
||||||
|
int extent[3] = {1, 1, 1};
|
||||||
|
this->mip_size_get(mip, extent);
|
||||||
|
|
||||||
|
size_t sample_len = extent[0] * extent[1] * extent[2];
|
||||||
|
size_t sample_size = to_bytesize(format_, type);
|
||||||
|
size_t texture_size = sample_len * sample_size;
|
||||||
|
|
||||||
|
/* AMD Pro driver have a bug that write 8 bytes past buffer size
|
||||||
|
* if the texture is big. (see T66573) */
|
||||||
|
void *data = MEM_mallocN(texture_size + 8, "GPU_texture_read");
|
||||||
|
|
||||||
|
GLenum gl_format = to_gl_data_format(format_);
|
||||||
|
GLenum gl_type = to_gl(type);
|
||||||
|
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
glGetTextureImage(tex_id_, mip, gl_format, gl_type, texture_size, data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
if (type_ == GPU_TEXTURE_CUBE) {
|
||||||
|
size_t cube_face_size = texture_size / 6;
|
||||||
|
char *face_data = (char *)data;
|
||||||
|
for (int i = 0; i < 6; i++, face_data += cube_face_size) {
|
||||||
|
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, mip, gl_format, gl_type, face_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glGetTexImage(target_, mip, gl_format, gl_type, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Getters & setters
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
void GLTexture::swizzle_set(const char swizzle[4])
|
||||||
|
{
|
||||||
|
GLint gl_swizzle[4] = {(GLint)swizzle_to_gl(swizzle[0]),
|
||||||
|
(GLint)swizzle_to_gl(swizzle[1]),
|
||||||
|
(GLint)swizzle_to_gl(swizzle[2]),
|
||||||
|
(GLint)swizzle_to_gl(swizzle[3])};
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
glTextureParameteriv(tex_id_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
glTexParameteriv(target_, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::mip_range_set(int min, int max)
|
||||||
|
{
|
||||||
|
BLI_assert(min <= max && min >= 0 && max <= mipmaps_);
|
||||||
|
mip_min_ = min;
|
||||||
|
mip_max_ = max;
|
||||||
|
if (GLEW_ARB_direct_state_access) {
|
||||||
|
glTextureParameteri(tex_id_, GL_TEXTURE_BASE_LEVEL, min);
|
||||||
|
glTextureParameteri(tex_id_, GL_TEXTURE_MAX_LEVEL, max);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GLContext::state_manager_active_get()->texture_bind_temp(this);
|
||||||
|
glTexParameteri(target_, GL_TEXTURE_BASE_LEVEL, min);
|
||||||
|
glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GPUFrameBuffer *GLTexture::framebuffer_get(void)
|
||||||
|
{
|
||||||
|
if (framebuffer_) {
|
||||||
|
return framebuffer_;
|
||||||
|
}
|
||||||
|
BLI_assert(!(type_ & (GPU_TEXTURE_ARRAY | GPU_TEXTURE_CUBE | GPU_TEXTURE_1D | GPU_TEXTURE_3D)));
|
||||||
|
/* TODO(fclem) cleanup this. Don't use GPU object but blender::gpu ones. */
|
||||||
|
GPUTexture *gputex = reinterpret_cast<GPUTexture *>(static_cast<Texture *>(this));
|
||||||
|
framebuffer_ = GPU_framebuffer_create(name_);
|
||||||
|
GPU_framebuffer_texture_attach(framebuffer_, gputex, 0, 0);
|
||||||
|
return framebuffer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Sampler objects
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
GLuint GLTexture::samplers_[GPU_SAMPLER_MAX] = {0};
|
||||||
|
|
||||||
|
void GLTexture::samplers_init(void)
|
||||||
|
{
|
||||||
|
glGenSamplers(GPU_SAMPLER_MAX, samplers_);
|
||||||
|
for (int i = 0; i <= GPU_SAMPLER_ICON - 1; i++) {
|
||||||
|
eGPUSamplerState state = static_cast<eGPUSamplerState>(i);
|
||||||
|
GLenum clamp_type = (state & GPU_SAMPLER_CLAMP_BORDER) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
|
||||||
|
GLenum wrap_s = (state & GPU_SAMPLER_REPEAT_S) ? GL_REPEAT : clamp_type;
|
||||||
|
GLenum wrap_t = (state & GPU_SAMPLER_REPEAT_T) ? GL_REPEAT : clamp_type;
|
||||||
|
GLenum wrap_r = (state & GPU_SAMPLER_REPEAT_R) ? GL_REPEAT : clamp_type;
|
||||||
|
GLenum mag_filter = (state & GPU_SAMPLER_FILTER) ? GL_LINEAR : GL_NEAREST;
|
||||||
|
GLenum min_filter = (state & GPU_SAMPLER_FILTER) ?
|
||||||
|
((state & GPU_SAMPLER_MIPMAP) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) :
|
||||||
|
((state & GPU_SAMPLER_MIPMAP) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
|
||||||
|
GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
|
||||||
|
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_WRAP_S, wrap_s);
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_WRAP_T, wrap_t);
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_WRAP_R, wrap_r);
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_MIN_FILTER, min_filter);
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_COMPARE_MODE, compare_mode);
|
||||||
|
glSamplerParameteri(samplers_[i], GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
|
|
||||||
|
/** Other states are left to default:
|
||||||
|
* - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
|
||||||
|
* - GL_TEXTURE_MIN_LOD is -1000.
|
||||||
|
* - GL_TEXTURE_MAX_LOD is 1000.
|
||||||
|
* - GL_TEXTURE_LOD_BIAS is 0.0f.
|
||||||
|
**/
|
||||||
|
}
|
||||||
|
samplers_update();
|
||||||
|
|
||||||
|
/* Custom sampler for icons. */
|
||||||
|
GLuint icon_sampler = samplers_[GPU_SAMPLER_ICON];
|
||||||
|
glSamplerParameteri(icon_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||||
|
glSamplerParameteri(icon_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glSamplerParameterf(icon_sampler, GL_TEXTURE_LOD_BIAS, -0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::samplers_update(void)
|
||||||
|
{
|
||||||
|
if (!GLEW_EXT_texture_filter_anisotropic) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float max_anisotropy = 1.0f;
|
||||||
|
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
|
||||||
|
|
||||||
|
float aniso_filter = max_ff(max_anisotropy, U.anisotropic_filter);
|
||||||
|
|
||||||
|
for (int i = 0; i <= GPU_SAMPLER_ICON - 1; i++) {
|
||||||
|
eGPUSamplerState state = static_cast<eGPUSamplerState>(i);
|
||||||
|
if (state & GPU_SAMPLER_MIPMAP) {
|
||||||
|
glSamplerParameterf(samplers_[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso_filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::samplers_free(void)
|
||||||
|
{
|
||||||
|
glDeleteSamplers(GPU_SAMPLER_MAX, samplers_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Proxy texture
|
||||||
|
*
|
||||||
|
* Dummy texture to see if the implementation supports the requested size.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/* NOTE: This only checks if this mipmap is valid / supported.
|
||||||
|
* TODO(fclem) make the check cover the whole mipmap chain. */
|
||||||
|
bool GLTexture::proxy_check(int mip)
|
||||||
|
{
|
||||||
|
/* Manual validation first, since some implementation have issues with proxy creation. */
|
||||||
|
int max_size = GPU_max_texture_size();
|
||||||
|
int max_3d_size = GPU_max_texture_3d_size();
|
||||||
|
int max_cube_size = GPU_max_cube_map_size();
|
||||||
|
int size[3] = {1, 1, 1};
|
||||||
|
this->mip_size_get(mip, size);
|
||||||
|
|
||||||
|
if (type_ & GPU_TEXTURE_ARRAY) {
|
||||||
|
if (this->layer_count() > GPU_max_texture_layers()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_ == GPU_TEXTURE_3D) {
|
||||||
|
if (size[0] > max_3d_size || size[1] > max_3d_size || size[2] > max_3d_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_2D) {
|
||||||
|
if (size[0] > max_size || size[1] > max_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_1D) {
|
||||||
|
if (size[0] > max_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((type_ & ~GPU_TEXTURE_ARRAY) == GPU_TEXTURE_CUBE) {
|
||||||
|
if (size[0] > max_cube_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY) ||
|
||||||
|
GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_OFFICIAL) ||
|
||||||
|
GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL)) {
|
||||||
|
/* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check.
|
||||||
|
* (see T55888, T56185, T59351).
|
||||||
|
* Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue,
|
||||||
|
* it just states that the OGL implementation can support the texture.
|
||||||
|
* So we already manually check the maximum size and maximum number of layers.
|
||||||
|
* Same thing happens on Nvidia/macOS 10.15 (T78175). */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type_ == GPU_TEXTURE_CUBE_ARRAY) &&
|
||||||
|
GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) {
|
||||||
|
/* Special fix for T79703. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum gl_proxy = to_gl_proxy(type_);
|
||||||
|
GLenum internal_format = to_gl_internal_format(format_);
|
||||||
|
GLenum gl_format = to_gl_data_format(format_);
|
||||||
|
GLenum gl_type = to_gl(to_data_format(format_));
|
||||||
|
/* Small exception. */
|
||||||
|
int dimensions = (type_ == GPU_TEXTURE_CUBE) ? 2 : this->dimensions_count();
|
||||||
|
|
||||||
|
if (format_flag_ & GPU_FORMAT_COMPRESSED) {
|
||||||
|
size_t img_size = ((size[0] + 3) / 4) * ((size[1] + 3) / 4) * to_block_size(format_);
|
||||||
|
switch (dimensions) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glCompressedTexImage1D(gl_proxy, mip, size[0], 0, gl_format, img_size, NULL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glCompressedTexImage2D(gl_proxy, mip, UNPACK2(size), 0, gl_format, img_size, NULL);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glCompressedTexImage3D(gl_proxy, mip, UNPACK3(size), 0, gl_format, img_size, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (dimensions) {
|
||||||
|
default:
|
||||||
|
case 1:
|
||||||
|
glTexImage1D(gl_proxy, mip, internal_format, size[0], 0, gl_format, gl_type, NULL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
glTexImage2D(gl_proxy, mip, internal_format, UNPACK2(size), 0, gl_format, gl_type, NULL);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
glTexImage3D(gl_proxy, mip, internal_format, UNPACK3(size), 0, gl_format, gl_type, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
glGetTexLevelParameteriv(gl_proxy, 0, GL_TEXTURE_WIDTH, &width);
|
||||||
|
return (width > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
void GLTexture::check_feedback_loop(void)
|
||||||
|
{
|
||||||
|
/* Recursive downsample workaround break this check.
|
||||||
|
* See recursive_downsample() for more infos. */
|
||||||
|
if (GPU_mip_render_workaround()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GLFrameBuffer *fb = static_cast<GLFrameBuffer *>(GPU_context_active_get()->active_fb);
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(fb_); i++) {
|
||||||
|
if (fb_[i] == fb) {
|
||||||
|
GPUAttachmentType type = fb_attachment_[i];
|
||||||
|
GPUAttachment attachment = fb->attachments_[type];
|
||||||
|
if (attachment.mip <= mip_max_ && attachment.mip >= mip_min_) {
|
||||||
|
char msg[256];
|
||||||
|
SNPRINTF(msg,
|
||||||
|
"Feedback loop: Trying to bind a texture (%s) with mip range %d-%d but mip %d is "
|
||||||
|
"attached to the active framebuffer (%s)",
|
||||||
|
name_,
|
||||||
|
mip_min_,
|
||||||
|
mip_max_,
|
||||||
|
attachment.mip,
|
||||||
|
fb->name_);
|
||||||
|
debug::raise_gl_error(msg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(fclem) Legacy. Should be removed at some point. */
|
||||||
|
uint GLTexture::gl_bindcode_get(void) const
|
||||||
|
{
|
||||||
|
return tex_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::gpu
|
@@ -31,14 +31,250 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "BLI_assert.h"
|
#include "BLI_assert.h"
|
||||||
|
|
||||||
|
#include "gpu_texture_private.hh"
|
||||||
|
|
||||||
#include "glew-mx.h"
|
#include "glew-mx.h"
|
||||||
|
|
||||||
|
struct GPUFrameBuffer;
|
||||||
|
|
||||||
namespace blender {
|
namespace blender {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
static GLenum to_gl(eGPUDataFormat format)
|
class GLTexture : public Texture {
|
||||||
|
friend class GLStateManager;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** All samplers states. */
|
||||||
|
static GLuint samplers_[GPU_SAMPLER_MAX];
|
||||||
|
|
||||||
|
/** Target to bind the texture to (GL_TEXTURE_1D, GL_TEXTURE_2D, etc...)*/
|
||||||
|
GLenum target_ = -1;
|
||||||
|
/** opengl identifier for texture. */
|
||||||
|
GLuint tex_id_ = 0;
|
||||||
|
/** Legacy workaround for texture copy. Created when using framebuffer_get(). */
|
||||||
|
struct GPUFrameBuffer *framebuffer_ = NULL;
|
||||||
|
/** True if this texture is bound to at least one texture unit. */
|
||||||
|
/* TODO(fclem) How do we ensure thread safety here? */
|
||||||
|
bool is_bound_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GLTexture(const char *name);
|
||||||
|
~GLTexture();
|
||||||
|
|
||||||
|
void update_sub(
|
||||||
|
int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data) override;
|
||||||
|
|
||||||
|
void generate_mipmap(void) override;
|
||||||
|
void copy_to(Texture *tex) override;
|
||||||
|
void clear(eGPUDataFormat format, const void *data) override;
|
||||||
|
void swizzle_set(const char swizzle_mask[4]) override;
|
||||||
|
void mip_range_set(int min, int max) override;
|
||||||
|
void *read(int mip, eGPUDataFormat format) override;
|
||||||
|
|
||||||
|
void check_feedback_loop(void);
|
||||||
|
|
||||||
|
/* TODO(fclem) Legacy. Should be removed at some point. */
|
||||||
|
uint gl_bindcode_get(void) const override;
|
||||||
|
|
||||||
|
static void samplers_init(void);
|
||||||
|
static void samplers_free(void);
|
||||||
|
static void samplers_update(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool init_internal(void) override;
|
||||||
|
bool init_internal(GPUVertBuf *vbo) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool proxy_check(int mip);
|
||||||
|
void ensure_mipmaps(int mip);
|
||||||
|
void update_sub_direct_state_access(
|
||||||
|
int mip, int offset[3], int extent[3], GLenum gl_format, GLenum gl_type, const void *data);
|
||||||
|
GPUFrameBuffer *framebuffer_get(void);
|
||||||
|
|
||||||
|
MEM_CXX_CLASS_ALLOC_FUNCS("GLTexture")
|
||||||
|
};
|
||||||
|
|
||||||
|
inline GLenum to_gl_internal_format(eGPUTextureFormat format)
|
||||||
|
{
|
||||||
|
/* You can add any of the available type to this list
|
||||||
|
* For available types see GPU_texture.h */
|
||||||
|
switch (format) {
|
||||||
|
/* Formats texture & renderbuffer */
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
return GL_RGBA8UI;
|
||||||
|
case GPU_RGBA8I:
|
||||||
|
return GL_RGBA8I;
|
||||||
|
case GPU_RGBA8:
|
||||||
|
return GL_RGBA8;
|
||||||
|
case GPU_RGBA32UI:
|
||||||
|
return GL_RGBA32UI;
|
||||||
|
case GPU_RGBA32I:
|
||||||
|
return GL_RGBA32I;
|
||||||
|
case GPU_RGBA32F:
|
||||||
|
return GL_RGBA32F;
|
||||||
|
case GPU_RGBA16UI:
|
||||||
|
return GL_RGBA16UI;
|
||||||
|
case GPU_RGBA16I:
|
||||||
|
return GL_RGBA16I;
|
||||||
|
case GPU_RGBA16F:
|
||||||
|
return GL_RGBA16F;
|
||||||
|
case GPU_RGBA16:
|
||||||
|
return GL_RGBA16;
|
||||||
|
case GPU_RG8UI:
|
||||||
|
return GL_RG8UI;
|
||||||
|
case GPU_RG8I:
|
||||||
|
return GL_RG8I;
|
||||||
|
case GPU_RG8:
|
||||||
|
return GL_RG8;
|
||||||
|
case GPU_RG32UI:
|
||||||
|
return GL_RG32UI;
|
||||||
|
case GPU_RG32I:
|
||||||
|
return GL_RG32I;
|
||||||
|
case GPU_RG32F:
|
||||||
|
return GL_RG32F;
|
||||||
|
case GPU_RG16UI:
|
||||||
|
return GL_RG16UI;
|
||||||
|
case GPU_RG16I:
|
||||||
|
return GL_RG16I;
|
||||||
|
case GPU_RG16F:
|
||||||
|
return GL_RG16F;
|
||||||
|
case GPU_RG16:
|
||||||
|
return GL_RG16;
|
||||||
|
case GPU_R8UI:
|
||||||
|
return GL_R8UI;
|
||||||
|
case GPU_R8I:
|
||||||
|
return GL_R8I;
|
||||||
|
case GPU_R8:
|
||||||
|
return GL_R8;
|
||||||
|
case GPU_R32UI:
|
||||||
|
return GL_R32UI;
|
||||||
|
case GPU_R32I:
|
||||||
|
return GL_R32I;
|
||||||
|
case GPU_R32F:
|
||||||
|
return GL_R32F;
|
||||||
|
case GPU_R16UI:
|
||||||
|
return GL_R16UI;
|
||||||
|
case GPU_R16I:
|
||||||
|
return GL_R16I;
|
||||||
|
case GPU_R16F:
|
||||||
|
return GL_R16F;
|
||||||
|
case GPU_R16:
|
||||||
|
return GL_R16;
|
||||||
|
/* Special formats texture & renderbuffer */
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
return GL_R11F_G11F_B10F;
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return GL_DEPTH32F_STENCIL8;
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
return GL_DEPTH24_STENCIL8;
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
return GL_SRGB8_ALPHA8;
|
||||||
|
/* Texture only format */
|
||||||
|
case GPU_RGB16F:
|
||||||
|
return GL_RGB16F;
|
||||||
|
/* Special formats texture only */
|
||||||
|
case GPU_SRGB8_A8_DXT1:
|
||||||
|
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
||||||
|
case GPU_SRGB8_A8_DXT3:
|
||||||
|
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
||||||
|
case GPU_SRGB8_A8_DXT5:
|
||||||
|
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
||||||
|
case GPU_RGBA8_DXT1:
|
||||||
|
return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
|
case GPU_RGBA8_DXT3:
|
||||||
|
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
case GPU_RGBA8_DXT5:
|
||||||
|
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
/* Depth Formats */
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
return GL_DEPTH_COMPONENT32F;
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
return GL_DEPTH_COMPONENT24;
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
return GL_DEPTH_COMPONENT16;
|
||||||
|
default:
|
||||||
|
BLI_assert(!"Texture format incorrect or unsupported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GLenum to_gl_target(eGPUTextureType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case GPU_TEXTURE_1D:
|
||||||
|
return GL_TEXTURE_1D;
|
||||||
|
case GPU_TEXTURE_1D_ARRAY:
|
||||||
|
return GL_TEXTURE_1D_ARRAY;
|
||||||
|
case GPU_TEXTURE_2D:
|
||||||
|
return GL_TEXTURE_2D;
|
||||||
|
case GPU_TEXTURE_2D_ARRAY:
|
||||||
|
return GL_TEXTURE_2D_ARRAY;
|
||||||
|
case GPU_TEXTURE_3D:
|
||||||
|
return GL_TEXTURE_3D;
|
||||||
|
case GPU_TEXTURE_CUBE:
|
||||||
|
return GL_TEXTURE_CUBE_MAP;
|
||||||
|
case GPU_TEXTURE_CUBE_ARRAY:
|
||||||
|
return GL_TEXTURE_CUBE_MAP_ARRAY_ARB;
|
||||||
|
case GPU_TEXTURE_BUFFER:
|
||||||
|
return GL_TEXTURE_BUFFER;
|
||||||
|
default:
|
||||||
|
BLI_assert(0);
|
||||||
|
return GL_TEXTURE_1D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GLenum to_gl_proxy(eGPUTextureType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case GPU_TEXTURE_1D:
|
||||||
|
return GL_PROXY_TEXTURE_1D;
|
||||||
|
case GPU_TEXTURE_1D_ARRAY:
|
||||||
|
return GL_PROXY_TEXTURE_1D_ARRAY;
|
||||||
|
case GPU_TEXTURE_2D:
|
||||||
|
return GL_PROXY_TEXTURE_2D;
|
||||||
|
case GPU_TEXTURE_2D_ARRAY:
|
||||||
|
return GL_PROXY_TEXTURE_2D_ARRAY;
|
||||||
|
case GPU_TEXTURE_3D:
|
||||||
|
return GL_PROXY_TEXTURE_3D;
|
||||||
|
case GPU_TEXTURE_CUBE:
|
||||||
|
return GL_PROXY_TEXTURE_CUBE_MAP;
|
||||||
|
case GPU_TEXTURE_CUBE_ARRAY:
|
||||||
|
return GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB;
|
||||||
|
case GPU_TEXTURE_BUFFER:
|
||||||
|
default:
|
||||||
|
BLI_assert(0);
|
||||||
|
return GL_TEXTURE_1D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GLenum swizzle_to_gl(const char swizzle)
|
||||||
|
{
|
||||||
|
switch (swizzle) {
|
||||||
|
default:
|
||||||
|
case 'x':
|
||||||
|
case 'r':
|
||||||
|
return GL_RED;
|
||||||
|
case 'y':
|
||||||
|
case 'g':
|
||||||
|
return GL_GREEN;
|
||||||
|
case 'z':
|
||||||
|
case 'b':
|
||||||
|
return GL_BLUE;
|
||||||
|
case 'w':
|
||||||
|
case 'a':
|
||||||
|
return GL_ALPHA;
|
||||||
|
case '0':
|
||||||
|
return GL_ZERO;
|
||||||
|
case '1':
|
||||||
|
return GL_ONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GLenum to_gl(eGPUDataFormat format)
|
||||||
{
|
{
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GPU_DATA_FLOAT:
|
case GPU_DATA_FLOAT:
|
||||||
@@ -59,8 +295,67 @@ static GLenum to_gl(eGPUDataFormat format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Definitely not complete, edit according to the gl specification. */
|
||||||
|
inline GLenum to_gl_data_format(eGPUTextureFormat format)
|
||||||
|
{
|
||||||
|
/* You can add any of the available type to this list
|
||||||
|
* For available types see GPU_texture.h */
|
||||||
|
switch (format) {
|
||||||
|
case GPU_R8I:
|
||||||
|
case GPU_R8UI:
|
||||||
|
case GPU_R16I:
|
||||||
|
case GPU_R16UI:
|
||||||
|
case GPU_R32I:
|
||||||
|
case GPU_R32UI:
|
||||||
|
return GL_RED_INTEGER;
|
||||||
|
case GPU_RG8I:
|
||||||
|
case GPU_RG8UI:
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_RG32I:
|
||||||
|
case GPU_RG32UI:
|
||||||
|
return GL_RG_INTEGER;
|
||||||
|
case GPU_RGBA8I:
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
case GPU_RGBA16I:
|
||||||
|
case GPU_RGBA16UI:
|
||||||
|
case GPU_RGBA32I:
|
||||||
|
case GPU_RGBA32UI:
|
||||||
|
return GL_RGBA_INTEGER;
|
||||||
|
case GPU_R8:
|
||||||
|
case GPU_R16:
|
||||||
|
case GPU_R16F:
|
||||||
|
case GPU_R32F:
|
||||||
|
return GL_RED;
|
||||||
|
case GPU_RG8:
|
||||||
|
case GPU_RG16:
|
||||||
|
case GPU_RG16F:
|
||||||
|
case GPU_RG32F:
|
||||||
|
return GL_RG;
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
case GPU_RGB16F:
|
||||||
|
return GL_RGB;
|
||||||
|
case GPU_RGBA8:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
case GPU_RGBA16:
|
||||||
|
case GPU_RGBA16F:
|
||||||
|
case GPU_RGBA32F:
|
||||||
|
return GL_RGBA;
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return GL_DEPTH_STENCIL;
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
return GL_DEPTH_COMPONENT;
|
||||||
|
default:
|
||||||
|
BLI_assert(!"Texture format incorrect or unsupported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Assume Unorm / Float target. Used with glReadPixels. */
|
/* Assume Unorm / Float target. Used with glReadPixels. */
|
||||||
static GLenum channel_len_to_gl(int channel_len)
|
inline GLenum channel_len_to_gl(int channel_len)
|
||||||
{
|
{
|
||||||
switch (channel_len) {
|
switch (channel_len) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@@ -736,11 +736,12 @@ const char *IMB_ffmpeg_last_error(void);
|
|||||||
*
|
*
|
||||||
* \attention defined in util_gpu.c
|
* \attention defined in util_gpu.c
|
||||||
*/
|
*/
|
||||||
struct GPUTexture *IMB_create_gpu_texture(struct ImBuf *ibuf,
|
struct GPUTexture *IMB_create_gpu_texture(const char *name,
|
||||||
|
struct ImBuf *ibuf,
|
||||||
bool use_high_bitdepth,
|
bool use_high_bitdepth,
|
||||||
bool use_premult);
|
bool use_premult);
|
||||||
struct GPUTexture *IMB_touch_gpu_texture(
|
struct GPUTexture *IMB_touch_gpu_texture(
|
||||||
struct ImBuf *ibuf, int w, int h, int layers, bool use_high_bitdepth);
|
const char *name, struct ImBuf *ibuf, int w, int h, int layers, bool use_high_bitdepth);
|
||||||
void IMB_update_gpu_texture_sub(struct GPUTexture *tex,
|
void IMB_update_gpu_texture_sub(struct GPUTexture *tex,
|
||||||
struct ImBuf *ibuf,
|
struct ImBuf *ibuf,
|
||||||
int x,
|
int x,
|
||||||
|
@@ -159,14 +159,20 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
|
|||||||
|
|
||||||
/* The ibuf is only here to detect the storage type. The produced texture will have undefined
|
/* The ibuf is only here to detect the storage type. The produced texture will have undefined
|
||||||
* content. It will need to be populated by using IMB_update_gpu_texture_sub(). */
|
* content. It will need to be populated by using IMB_update_gpu_texture_sub(). */
|
||||||
GPUTexture *IMB_touch_gpu_texture(ImBuf *ibuf, int w, int h, int layers, bool use_high_bitdepth)
|
GPUTexture *IMB_touch_gpu_texture(
|
||||||
|
const char *name, ImBuf *ibuf, int w, int h, int layers, bool use_high_bitdepth)
|
||||||
{
|
{
|
||||||
eGPUDataFormat data_format;
|
eGPUDataFormat data_format;
|
||||||
eGPUTextureFormat tex_format;
|
eGPUTextureFormat tex_format;
|
||||||
imb_gpu_get_format(ibuf, use_high_bitdepth, &data_format, &tex_format);
|
imb_gpu_get_format(ibuf, use_high_bitdepth, &data_format, &tex_format);
|
||||||
|
|
||||||
GPUTexture *tex = GPU_texture_create_nD(
|
GPUTexture *tex;
|
||||||
w, h, layers, 2, NULL, tex_format, data_format, 0, false, NULL);
|
if (layers > 0) {
|
||||||
|
tex = GPU_texture_create_2d_array(name, w, h, layers, 1, tex_format, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tex = GPU_texture_create_2d(name, w, h, 9999, tex_format, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
GPU_texture_anisotropic_filter(tex, true);
|
GPU_texture_anisotropic_filter(tex, true);
|
||||||
return tex;
|
return tex;
|
||||||
@@ -205,7 +211,10 @@ void IMB_update_gpu_texture_sub(GPUTexture *tex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUTexture *IMB_create_gpu_texture(ImBuf *ibuf, bool use_high_bitdepth, bool use_premult)
|
GPUTexture *IMB_create_gpu_texture(const char *name,
|
||||||
|
ImBuf *ibuf,
|
||||||
|
bool use_high_bitdepth,
|
||||||
|
bool use_premult)
|
||||||
{
|
{
|
||||||
GPUTexture *tex = NULL;
|
GPUTexture *tex = NULL;
|
||||||
const int size[2] = {GPU_texture_size_with_limit(ibuf->x), GPU_texture_size_with_limit(ibuf->y)};
|
const int size[2] = {GPU_texture_size_with_limit(ibuf->x), GPU_texture_size_with_limit(ibuf->y)};
|
||||||
@@ -224,8 +233,12 @@ GPUTexture *IMB_create_gpu_texture(ImBuf *ibuf, bool use_high_bitdepth, bool use
|
|||||||
fprintf(stderr, "Unable to load non-power-of-two DXT image resolution,");
|
fprintf(stderr, "Unable to load non-power-of-two DXT image resolution,");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tex = GPU_texture_create_compressed(
|
tex = GPU_texture_create_compressed_2d(name,
|
||||||
ibuf->x, ibuf->y, ibuf->dds_data.nummipmaps, compressed_format, ibuf->dds_data.data);
|
ibuf->x,
|
||||||
|
ibuf->y,
|
||||||
|
ibuf->dds_data.nummipmaps,
|
||||||
|
compressed_format,
|
||||||
|
ibuf->dds_data.data);
|
||||||
|
|
||||||
if (tex != NULL) {
|
if (tex != NULL) {
|
||||||
return tex;
|
return tex;
|
||||||
@@ -248,7 +261,8 @@ GPUTexture *IMB_create_gpu_texture(ImBuf *ibuf, bool use_high_bitdepth, bool use
|
|||||||
void *data = imb_gpu_get_data(ibuf, do_rescale, size, compress_as_srgb, use_premult, &freebuf);
|
void *data = imb_gpu_get_data(ibuf, do_rescale, size, compress_as_srgb, use_premult, &freebuf);
|
||||||
|
|
||||||
/* Create Texture. */
|
/* Create Texture. */
|
||||||
tex = GPU_texture_create_nD(UNPACK2(size), 0, 2, data, tex_format, data_format, 0, false, NULL);
|
tex = GPU_texture_create_2d(name, UNPACK2(size), 9999, tex_format, NULL);
|
||||||
|
GPU_texture_update(tex, data_format, data);
|
||||||
|
|
||||||
GPU_texture_anisotropic_filter(tex, true);
|
GPU_texture_anisotropic_filter(tex, true);
|
||||||
|
|
||||||
|
@@ -364,8 +364,7 @@ static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
|
|||||||
|
|
||||||
static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||||
{
|
{
|
||||||
GPU_samplers_free();
|
GPU_samplers_update();
|
||||||
GPU_samplers_init();
|
|
||||||
rna_userdef_update(bmain, scene, ptr);
|
rna_userdef_update(bmain, scene, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2217,13 +2217,11 @@ static void radial_control_set_tex(RadialControl *rc)
|
|||||||
rc->use_secondary_tex,
|
rc->use_secondary_tex,
|
||||||
!ELEM(rc->subtype, PROP_NONE, PROP_PIXEL, PROP_DISTANCE)))) {
|
!ELEM(rc->subtype, PROP_NONE, PROP_PIXEL, PROP_DISTANCE)))) {
|
||||||
|
|
||||||
rc->texture = GPU_texture_create_nD(
|
rc->texture = GPU_texture_create_2d(
|
||||||
ibuf->x, ibuf->y, 0, 2, ibuf->rect_float, GPU_R8, GPU_DATA_FLOAT, 0, false, NULL);
|
"radial_control", ibuf->x, ibuf->y, 1, GPU_R8, ibuf->rect_float);
|
||||||
GPU_texture_filter_mode(rc->texture, true);
|
|
||||||
|
|
||||||
GPU_texture_bind(rc->texture, 0);
|
GPU_texture_filter_mode(rc->texture, true);
|
||||||
GPU_texture_swizzle_set(rc->texture, "111r");
|
GPU_texture_swizzle_set(rc->texture, "111r");
|
||||||
GPU_texture_unbind(rc->texture);
|
|
||||||
|
|
||||||
MEM_freeN(ibuf->rect_float);
|
MEM_freeN(ibuf->rect_float);
|
||||||
MEM_freeN(ibuf);
|
MEM_freeN(ibuf);
|
||||||
|
Reference in New Issue
Block a user