mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-09 15:09:50 +03:00
Added support for OpenGL 4.1 and 4.2. Shared Storage/Uniform Buffer
This commit is contained in:
+268
-4
@@ -412,7 +412,10 @@ void render_data::init() {
|
||||
buffer_shader.Create(sizeof(obj_shader_data));
|
||||
buffer_scene.Create(sizeof(obj_scene_data));
|
||||
buffer_batch.Create(sizeof(obj_batch_data));
|
||||
buffer_skinning.Create(sizeof(obj_skinning_data));
|
||||
if (GLAD_GL_VERSION_4_3)
|
||||
buffer_skinning.Create(sizeof(obj_skinning_data));
|
||||
else
|
||||
buffer_skinning_ubo.Create(sizeof(obj_skinning_data));
|
||||
|
||||
buffer_shader_data.reset();
|
||||
enum_or(flags, RENDER_DATA_SHADER_UPDATE);
|
||||
@@ -423,7 +426,10 @@ void render_data::init() {
|
||||
}
|
||||
|
||||
void render_data::free() {
|
||||
buffer_skinning.Destroy();
|
||||
if (GLAD_GL_VERSION_4_3)
|
||||
buffer_skinning.Destroy();
|
||||
else
|
||||
buffer_skinning_ubo.Destroy();
|
||||
buffer_batch.Destroy();
|
||||
buffer_scene.Destroy();
|
||||
buffer_shader.Destroy();
|
||||
@@ -493,8 +499,11 @@ void render_data::set(render_context* rctx) {
|
||||
buffer_scene.Bind(1);
|
||||
buffer_batch.Bind(2);
|
||||
|
||||
if (uniform_value[U_SKINNING])
|
||||
buffer_skinning.Bind(0);
|
||||
if (uniform_value[U_SKINNING] && !sv_shared_storage_uniform_buffer)
|
||||
if (GLAD_GL_VERSION_4_3)
|
||||
buffer_skinning.Bind(0);
|
||||
else
|
||||
buffer_skinning_ubo.Bind(6);
|
||||
}
|
||||
|
||||
void render_data::set_shader(uint32_t index) {
|
||||
@@ -504,6 +513,68 @@ void render_data::set_shader(uint32_t index) {
|
||||
enum_or(flags, RENDER_DATA_SHADER_UPDATE);
|
||||
}
|
||||
|
||||
bool render_context::shared_storage_buffer::can_fill_data(size_t size) {
|
||||
return (size + align_val(offset, sv_min_storage_buffer_alignment)) <= this->size;
|
||||
}
|
||||
|
||||
void render_context::shared_storage_buffer::create(size_t size) {
|
||||
if (buffer)
|
||||
return;
|
||||
|
||||
size = size / sv_min_storage_buffer_alignment * sv_min_storage_buffer_alignment;
|
||||
|
||||
buffer.Create(size);
|
||||
data = force_malloc(size);
|
||||
memset(data, 0, size);
|
||||
offset = 0;
|
||||
this->size = size;
|
||||
}
|
||||
|
||||
void render_context::shared_storage_buffer::destroy() {
|
||||
buffer.Destroy();
|
||||
free_def(data);
|
||||
}
|
||||
|
||||
size_t render_context::shared_storage_buffer::fill_data(const void* data, size_t size) {
|
||||
size_t offset = align_val(this->offset, sv_min_storage_buffer_alignment);
|
||||
if (offset != this->offset)
|
||||
memset((void*)((size_t)this->data + this->offset), 0, offset - this->offset);
|
||||
memcpy((void*)((size_t)this->data + offset), data, size);
|
||||
this->offset = offset + size;
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool render_context::shared_uniform_buffer::can_fill_data(size_t size) {
|
||||
return (size + align_val(offset, sv_min_uniform_buffer_alignment)) <= this->size;
|
||||
}
|
||||
|
||||
void render_context::shared_uniform_buffer::create(size_t size) {
|
||||
if (buffer)
|
||||
return;
|
||||
|
||||
size = size / sv_min_uniform_buffer_alignment * sv_min_uniform_buffer_alignment;
|
||||
|
||||
buffer.Create(size);
|
||||
data = force_malloc(size);
|
||||
memset(data, 0, size);
|
||||
offset = 0;
|
||||
this->size = size;
|
||||
}
|
||||
|
||||
void render_context::shared_uniform_buffer::destroy() {
|
||||
buffer.Destroy();
|
||||
free_def(data);
|
||||
}
|
||||
|
||||
size_t render_context::shared_uniform_buffer::fill_data(const void* data, size_t size) {
|
||||
size_t offset = align_val(this->offset, sv_min_uniform_buffer_alignment);
|
||||
if (offset != this->offset)
|
||||
memset((void*)((size_t)this->data + this->offset), 0, offset - this->offset);
|
||||
memcpy((void*)((size_t)this->data + offset), data, size);
|
||||
this->offset = offset + size;
|
||||
return offset;
|
||||
}
|
||||
|
||||
render_context::render_context() : litproj(), chara_reflect(), chara_refract(), box_vao(), lens_ghost_vao(),
|
||||
common_vao(), empty_texture_2d(), empty_texture_cube_map(), samplers(), render_samplers(), sprite_samplers(),
|
||||
sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_width(), screen_height() {
|
||||
@@ -689,9 +760,30 @@ sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_wi
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
|
||||
|
||||
max_uniform_block_size = min_def((uint32_t)sv_max_uniform_buffer_size, 64u * 1024);
|
||||
|
||||
if (GLAD_GL_VERSION_4_3)
|
||||
max_storage_block_size = min_def((uint32_t)sv_max_storage_buffer_size, 1024u * 1024);
|
||||
}
|
||||
|
||||
render_context::~render_context() {
|
||||
if (sv_shared_storage_uniform_buffer) {
|
||||
shared_uniform_buffer_entries.clear();
|
||||
|
||||
for (render_context::shared_uniform_buffer& i : shared_uniform_buffers)
|
||||
i.destroy();
|
||||
shared_uniform_buffers.clear();
|
||||
|
||||
if (GLAD_GL_VERSION_4_3) {
|
||||
shared_storage_buffer_entries.clear();
|
||||
|
||||
for (render_context::shared_storage_buffer& i : shared_storage_buffers)
|
||||
i.destroy();
|
||||
shared_storage_buffers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
glDeleteSamplers(3, sprite_samplers);
|
||||
glDeleteSamplers(4, render_samplers);
|
||||
glDeleteSamplers(18, samplers);
|
||||
@@ -883,6 +975,44 @@ void render_context::resize(int32_t render_width, int32_t render_height,
|
||||
}
|
||||
}
|
||||
|
||||
void render_context::add_shared_storage_uniform_buffer_data(size_t index,
|
||||
const void* data, size_t size, size_t buffer_size, bool storage) {
|
||||
if (storage) {
|
||||
render_context::shared_storage_buffer* buffer = 0;
|
||||
for (render_context::shared_storage_buffer& i : shared_storage_buffers)
|
||||
if (i.can_fill_data(buffer_size)) {
|
||||
buffer = &i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
shared_storage_buffers.push_back({});
|
||||
buffer = &shared_storage_buffers.back();
|
||||
buffer->create(max_storage_block_size);
|
||||
}
|
||||
|
||||
size_t offset = buffer->fill_data(data, size);
|
||||
shared_storage_buffer_entries.insert({ index, { buffer->buffer, offset, buffer_size } });
|
||||
}
|
||||
else {
|
||||
render_context::shared_uniform_buffer* buffer = 0;
|
||||
for (render_context::shared_uniform_buffer& i : shared_uniform_buffers)
|
||||
if (i.can_fill_data(buffer_size)) {
|
||||
buffer = &i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
shared_uniform_buffers.push_back({});
|
||||
buffer = &shared_uniform_buffers.back();
|
||||
buffer->create(max_uniform_block_size);
|
||||
}
|
||||
|
||||
size_t offset = buffer->fill_data(data, size);
|
||||
shared_uniform_buffer_entries.insert({ index, { buffer->buffer, offset, buffer_size } });
|
||||
}
|
||||
}
|
||||
|
||||
void render_context::get_scene_fog_params(render_context::fog_params& value) {
|
||||
render_data* data = &this->data;
|
||||
value.depth_color = data->buffer_scene_data.g_fog_depth_color;
|
||||
@@ -912,6 +1042,140 @@ void render_context::get_scene_light(vec4* light_env_stage_diffuse,
|
||||
*light_env_chara_specular = data->buffer_scene_data.g_light_env_chara_specular;
|
||||
}
|
||||
|
||||
bool render_context::get_shared_storage_uniform_buffer_data(size_t index,
|
||||
GLuint& buffer, size_t& offset, size_t& size, bool storage) {
|
||||
if (storage) {
|
||||
auto elem = shared_storage_buffer_entries.find(index);
|
||||
if (elem == shared_storage_buffer_entries.end())
|
||||
return false;
|
||||
|
||||
buffer = elem->second.buffer;
|
||||
offset = elem->second.offset;
|
||||
size = elem->second.size;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
auto elem = shared_uniform_buffer_entries.find(index);
|
||||
if (elem == shared_uniform_buffer_entries.end())
|
||||
return false;
|
||||
|
||||
buffer = elem->second.buffer;
|
||||
offset = elem->second.offset;
|
||||
size = elem->second.size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void render_context::pre_proc() {
|
||||
if (sv_shared_storage_uniform_buffer) {
|
||||
auto add_obj_list = [](render_context* rctx, const mdl::ObjSubMeshArgs* args) {
|
||||
if (!args->mat_count || !args->mats)
|
||||
return;
|
||||
|
||||
if (GLAD_GL_VERSION_4_3) {
|
||||
if (rctx->shared_storage_buffer_entries.find((size_t)args->mats)
|
||||
!= rctx->shared_storage_buffer_entries.end())
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (rctx->shared_uniform_buffer_entries.find((size_t)args->mats)
|
||||
!= rctx->shared_uniform_buffer_entries.end())
|
||||
return;
|
||||
}
|
||||
|
||||
const int32_t mat_count = min_def(args->mat_count, 256);
|
||||
const mat4* mats = args->mats;
|
||||
vec4* g_joint_transforms = rctx->data.buffer_skinning_data.g_joint_transforms;
|
||||
|
||||
mat4 mat;
|
||||
for (int32_t i = 0; i < mat_count; i++, mats++, g_joint_transforms += 3) {
|
||||
mat4_transpose(mats, &mat);
|
||||
g_joint_transforms[0] = mat.row0;
|
||||
g_joint_transforms[1] = mat.row1;
|
||||
g_joint_transforms[2] = mat.row2;
|
||||
}
|
||||
|
||||
const size_t buffer_size = sizeof(vec4) * 3 * 256;
|
||||
const size_t size = sizeof(vec4) * 3 * mat_count;
|
||||
rctx->add_shared_storage_uniform_buffer_data((size_t)args->mats,
|
||||
rctx->data.buffer_skinning_data.g_joint_transforms, size, buffer_size, !!GLAD_GL_VERSION_4_3);
|
||||
};
|
||||
|
||||
for (int32_t type = 0; type < mdl::OBJ_TYPE_MAX; type++)
|
||||
for (mdl::ObjData*& i : disp_manager->obj[type])
|
||||
switch (i->kind) {
|
||||
case mdl::OBJ_KIND_NORMAL:
|
||||
add_obj_list(this, &i->args.sub_mesh);
|
||||
break;
|
||||
case mdl::OBJ_KIND_TRANSLUCENT:
|
||||
for (int32_t j = 0; j < i->args.translucent.count; j++)
|
||||
add_obj_list(this, i->args.translucent.sub_mesh[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int32_t type = 0; type < mdl::OBJ_TYPE_LOCAL_MAX; type++)
|
||||
for (mdl::ObjData*& i : disp_manager->obj_local[type])
|
||||
switch (i->kind) {
|
||||
case mdl::OBJ_KIND_NORMAL:
|
||||
add_obj_list(this, &i->args.sub_mesh);
|
||||
break;
|
||||
case mdl::OBJ_KIND_TRANSLUCENT:
|
||||
for (int32_t j = 0; j < i->args.translucent.count; j++)
|
||||
add_obj_list(this, i->args.translucent.sub_mesh[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int32_t type = 0; type < mdl::OBJ_TYPE_REFLECT_MAX; type++)
|
||||
for (mdl::ObjData*& i : disp_manager->obj_reflect[type])
|
||||
switch (i->kind) {
|
||||
case mdl::OBJ_KIND_NORMAL:
|
||||
add_obj_list(this, &i->args.sub_mesh);
|
||||
break;
|
||||
case mdl::OBJ_KIND_TRANSLUCENT:
|
||||
for (int32_t j = 0; j < i->args.translucent.count; j++)
|
||||
add_obj_list(this, i->args.translucent.sub_mesh[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (GLAD_GL_VERSION_4_3)
|
||||
for (render_context::shared_storage_buffer& i : shared_storage_buffers) {
|
||||
if (!i.offset)
|
||||
continue;
|
||||
|
||||
size_t align = align_val(i.offset, sv_min_storage_buffer_alignment) - i.offset;
|
||||
if (align)
|
||||
memset((void*)((size_t)i.data + i.offset), 0, align);
|
||||
i.buffer.WriteMemory(0, i.size, i.data);
|
||||
}
|
||||
|
||||
for (render_context::shared_uniform_buffer& i : shared_uniform_buffers) {
|
||||
if (!i.offset)
|
||||
continue;
|
||||
|
||||
size_t align = align_val(i.offset, sv_min_uniform_buffer_alignment) - i.offset;
|
||||
if (align)
|
||||
memset((void*)((size_t)i.data + i.offset), 0, align);
|
||||
i.buffer.WriteMemory(0, i.size, i.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_context::post_proc() {
|
||||
if (sv_shared_storage_uniform_buffer) {
|
||||
if (GLAD_GL_VERSION_4_3) {
|
||||
for (render_context::shared_storage_buffer& i : shared_storage_buffers)
|
||||
i.offset = 0;
|
||||
|
||||
shared_storage_buffer_entries.clear();
|
||||
}
|
||||
|
||||
for (render_context::shared_uniform_buffer& i : shared_uniform_buffers)
|
||||
i.offset = 0;
|
||||
|
||||
shared_uniform_buffer_entries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void render_context::set_batch_alpha_threshold(const float_t value) {
|
||||
render_data* data = &this->data;
|
||||
data->buffer_batch_data.g_max_alpha.z = value;
|
||||
|
||||
Reference in New Issue
Block a user