Batch freezing.
This commit is contained in:
		@ -601,9 +601,9 @@ rk_batch_t rk_create_batch(
 | 
				
			|||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ++binding;
 | 
					    binding += 1;
 | 
				
			||||||
    offset = 0;
 | 
					 | 
				
			||||||
    if (nparams) {
 | 
					    if (nparams) {
 | 
				
			||||||
 | 
					        offset = 0;
 | 
				
			||||||
        rk_parameter * param = batch->params;
 | 
					        rk_parameter * param = batch->params;
 | 
				
			||||||
        for (rk_param_format const * f = params_format; *f; ++f, ++param, ++binding) {
 | 
					        for (rk_param_format const * f = params_format; *f; ++f, ++param, ++binding) {
 | 
				
			||||||
            GLboolean const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0;
 | 
					            GLboolean const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0;
 | 
				
			||||||
@ -773,57 +773,6 @@ RK_EXPORT void rk_draw_triangles(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rk_fill_batch(
 | 
					 | 
				
			||||||
    rk_batch_t _batch,
 | 
					 | 
				
			||||||
    rk_uint count,
 | 
					 | 
				
			||||||
    rk_instance_flags const * flags,
 | 
					 | 
				
			||||||
    rk_mesh const * meshes,
 | 
					 | 
				
			||||||
    rk_ubyte const * const * params) {
 | 
					 | 
				
			||||||
    rk_batch const * const batch = reinterpret_cast<rk_batch const *>(_batch);
 | 
					 | 
				
			||||||
    if (!batch || !count || count > batch->max_size) {
 | 
					 | 
				
			||||||
        rk_printf("rk_fill_batch(): invalid params.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    bool const need_params = (batch->nparams > 0);
 | 
					 | 
				
			||||||
    bool got_params = false;
 | 
					 | 
				
			||||||
    bool all_params = false;
 | 
					 | 
				
			||||||
    if (params != nullptr) {
 | 
					 | 
				
			||||||
        all_params = true;
 | 
					 | 
				
			||||||
        for (rk_ubyte const * const * param = params; param < params + batch->nparams; ++param) {
 | 
					 | 
				
			||||||
            bool const got_param = (*param != nullptr);
 | 
					 | 
				
			||||||
            got_params |= got_param;
 | 
					 | 
				
			||||||
            all_params &= got_param;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    bool const got_all = (flags && meshes && (!need_params || all_params));
 | 
					 | 
				
			||||||
    if (count > batch->count && !got_all) {
 | 
					 | 
				
			||||||
        rk_printf("rk_fill_batch(): cannot grow without all flags, meshes and params.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    bool const need_sorting = (flags || meshes || count != batch->count);
 | 
					 | 
				
			||||||
    batch->count = count;
 | 
					 | 
				
			||||||
    if (flags) {
 | 
					 | 
				
			||||||
        memcpy(batch->flags, flags, count * sizeof(rk_instance_flags));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (meshes) {
 | 
					 | 
				
			||||||
        memcpy(batch->meshes, meshes, count * sizeof(rk_mesh));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (need_params && got_params) {
 | 
					 | 
				
			||||||
        rk_ubyte const * const * src = params;
 | 
					 | 
				
			||||||
        for (rk_parameter const * dst = batch->params; dst < batch->params + batch->nparams; ++dst, ++src) {
 | 
					 | 
				
			||||||
            dst->dirty = (*src || need_sorting);
 | 
					 | 
				
			||||||
            if (*src) {
 | 
					 | 
				
			||||||
                memcpy(dst->source, *src, count * dst->src_size);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (need_sorting) {
 | 
					 | 
				
			||||||
        batch->state = RK_BATCH_STATE_FILLED;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        batch->state = RK_BATCH_STATE_SORTED;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void rk_sort_batch(
 | 
					static void rk_sort_batch(
 | 
				
			||||||
    rk_batch const & batch) {
 | 
					    rk_batch const & batch) {
 | 
				
			||||||
    rk_instance_flags const * flags = batch.flags;
 | 
					    rk_instance_flags const * flags = batch.flags;
 | 
				
			||||||
@ -858,16 +807,17 @@ static void rk_sort_batch(
 | 
				
			|||||||
            command->base_instance = base - batch.indices;
 | 
					            command->base_instance = base - batch.indices;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        batch.ncommands = command - batch.commands;
 | 
					        batch.ncommands = command - batch.commands;
 | 
				
			||||||
 | 
					        if (rk_MultiDrawElementsIndirect && batch.ncommands) {
 | 
				
			||||||
 | 
					            glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, batch.ncommands * sizeof(rk_command), batch.commands);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (batch.nparams) {
 | 
					 | 
				
			||||||
    batch.state = RK_BATCH_STATE_SORTED;
 | 
					    batch.state = RK_BATCH_STATE_SORTED;
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        batch.state = RK_BATCH_STATE_PACKED;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rk_pack_batch(
 | 
					static void rk_pack_batch(
 | 
				
			||||||
    rk_batch const & batch) {
 | 
					    rk_batch const & batch) {
 | 
				
			||||||
 | 
					    if (batch.nparams) {
 | 
				
			||||||
 | 
					        glBindBuffer(GL_ARRAY_BUFFER, batch.params_buffer);
 | 
				
			||||||
        for (rk_parameter const * param = batch.params; param < batch.params + batch.nparams; ++param) {
 | 
					        for (rk_parameter const * param = batch.params; param < batch.params + batch.nparams; ++param) {
 | 
				
			||||||
            if (param->dirty) {
 | 
					            if (param->dirty) {
 | 
				
			||||||
                param->dirty = false;
 | 
					                param->dirty = false;
 | 
				
			||||||
@ -882,12 +832,87 @@ static void rk_pack_batch(
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    batch.state = RK_BATCH_STATE_PACKED;
 | 
					    batch.state = RK_BATCH_STATE_PACKED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_fill_batch(
 | 
				
			||||||
 | 
					    rk_batch_t _batch,
 | 
				
			||||||
 | 
					    rk_uint count,
 | 
				
			||||||
 | 
					    rk_instance_flags const * flags,
 | 
				
			||||||
 | 
					    rk_mesh const * meshes,
 | 
				
			||||||
 | 
					    rk_ubyte const * const * params) {
 | 
				
			||||||
 | 
					    rk_batch const * const batch = reinterpret_cast<rk_batch const *>(_batch);
 | 
				
			||||||
 | 
					    if (!batch || !count || count > batch->max_size) {
 | 
				
			||||||
 | 
					        rk_printf("rk_fill_batch(): invalid params.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bool got_any_params = false;
 | 
				
			||||||
 | 
					    bool got_all_params = !batch->nparams;
 | 
				
			||||||
 | 
					    if (batch->nparams) {
 | 
				
			||||||
 | 
					        got_all_params = (params != nullptr);
 | 
				
			||||||
 | 
					        if (params) {
 | 
				
			||||||
 | 
					            for (rk_ubyte const * const * param = params; param < params + batch->nparams; ++param) {
 | 
				
			||||||
 | 
					                bool const got_param = (*param != nullptr);
 | 
				
			||||||
 | 
					                got_any_params |= got_param;
 | 
				
			||||||
 | 
					                got_all_params &= got_param;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bool const is_empty = (batch->state < RK_BATCH_STATE_FILLED);
 | 
				
			||||||
 | 
					    bool const got_everything = (flags && meshes && got_all_params);
 | 
				
			||||||
 | 
					    bool const need_sorting = (is_empty || flags || meshes || count != batch->count);
 | 
				
			||||||
 | 
					    if (is_empty && !got_everything) {
 | 
				
			||||||
 | 
					        rk_printf("rk_fill_batch(): cannot freeze and empty batch.");
 | 
				
			||||||
 | 
					    } else if (count > batch->count && !got_everything) {
 | 
				
			||||||
 | 
					        rk_printf("rk_fill_batch(): cannot grow a frozen batch.");
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        batch->count = count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (flags) {
 | 
				
			||||||
 | 
					        memcpy(batch->flags, flags, batch->count * sizeof(rk_instance_flags));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (meshes) {
 | 
				
			||||||
 | 
					        memcpy(batch->meshes, meshes, batch->count * sizeof(rk_mesh));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (batch->nparams) {
 | 
				
			||||||
 | 
					        rk_parameter const * const last_param = batch->params + batch->nparams;
 | 
				
			||||||
 | 
					        if (got_any_params) {
 | 
				
			||||||
 | 
					            rk_ubyte const * const * src = params;
 | 
				
			||||||
 | 
					            for (rk_parameter const * dst = batch->params; dst < last_param; ++dst, ++src) {
 | 
				
			||||||
 | 
					                dst->dirty = (need_sorting || *src);
 | 
				
			||||||
 | 
					                if (*src) {
 | 
				
			||||||
 | 
					                    memcpy(dst->source, *src, batch->count * dst->src_size);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (need_sorting) {
 | 
				
			||||||
 | 
					            for (rk_parameter const * dst = batch->params; dst < last_param; ++dst) {
 | 
				
			||||||
 | 
					                dst->dirty = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (is_empty) {
 | 
				
			||||||
 | 
					        glBindVertexArray(batch->vertex_array);
 | 
				
			||||||
 | 
					        if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					            glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        rk_sort_batch(*batch);
 | 
				
			||||||
 | 
					        rk_pack_batch(*batch);
 | 
				
			||||||
 | 
					        if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					            glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        glBindVertexArray(0);
 | 
				
			||||||
 | 
					    } else if (need_sorting) {
 | 
				
			||||||
 | 
					        batch->state = RK_BATCH_STATE_FILLED;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        batch->state = RK_BATCH_STATE_SORTED;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rk_draw_batch(
 | 
					void rk_draw_batch(
 | 
				
			||||||
    rk_batch_t _batch) {
 | 
					    rk_batch_t _batch) {
 | 
				
			||||||
    rk_batch * const batch = reinterpret_cast<rk_batch *>(_batch);
 | 
					    rk_batch const * const batch = reinterpret_cast<rk_batch const *>(_batch);
 | 
				
			||||||
    if (!batch) {
 | 
					    if (!batch) {
 | 
				
			||||||
        rk_printf("rk_draw_batch(): invalid params.");
 | 
					        rk_printf("rk_draw_batch(): invalid params.");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
@ -896,29 +921,23 @@ void rk_draw_batch(
 | 
				
			|||||||
        rk_printf("rk_draw_batch(): invalid state.");
 | 
					        rk_printf("rk_draw_batch(): invalid state.");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (batch->state < RK_BATCH_STATE_SORTED) {
 | 
					 | 
				
			||||||
        rk_sort_batch(*batch);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (!batch->ncommands) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    glBindVertexArray(batch->vertex_array);
 | 
					    glBindVertexArray(batch->vertex_array);
 | 
				
			||||||
    if (rk_MultiDrawElementsIndirect) {
 | 
					    if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer);
 | 
					        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer);
 | 
				
			||||||
        glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, batch->ncommands * sizeof(rk_command), batch->commands);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (batch->state < RK_BATCH_STATE_PACKED) {
 | 
					    if (batch->state < RK_BATCH_STATE_SORTED) {
 | 
				
			||||||
        glBindBuffer(GL_ARRAY_BUFFER, batch->params_buffer);
 | 
					        rk_sort_batch(*batch);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (batch->state < RK_BATCH_STATE_PACKED && batch->nparams) {
 | 
				
			||||||
        rk_pack_batch(*batch);
 | 
					        rk_pack_batch(*batch);
 | 
				
			||||||
        glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rk_command const * const last_command = batch->commands + batch->ncommands;
 | 
					    if (batch->ncommands) {
 | 
				
			||||||
        if (rk_DrawElementsInstancedBaseInstance) {
 | 
					        if (rk_DrawElementsInstancedBaseInstance) {
 | 
				
			||||||
            if (rk_MultiDrawElementsIndirect) {
 | 
					            if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
                rk_MultiDrawElementsIndirect(
 | 
					                rk_MultiDrawElementsIndirect(
 | 
				
			||||||
                    GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, batch->ncommands, sizeof(rk_command));
 | 
					                    GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, batch->ncommands, sizeof(rk_command));
 | 
				
			||||||
            glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 | 
					                rk_command const * const last_command = batch->commands + batch->ncommands;
 | 
				
			||||||
                for (rk_command const * command = batch->commands; command < last_command; ++command) {
 | 
					                for (rk_command const * command = batch->commands; command < last_command; ++command) {
 | 
				
			||||||
                    rk_DrawElementsInstancedBaseInstance(
 | 
					                    rk_DrawElementsInstancedBaseInstance(
 | 
				
			||||||
                        GL_TRIANGLES, command->nvertices, GL_UNSIGNED_SHORT,
 | 
					                        GL_TRIANGLES, command->nvertices, GL_UNSIGNED_SHORT,
 | 
				
			||||||
@ -927,20 +946,25 @@ void rk_draw_batch(
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
        unsigned param_index = 0;
 | 
					            rk_command const * const last_command = batch->commands + batch->ncommands;
 | 
				
			||||||
            rk_parameter const * const last_param = batch->params + batch->nparams;
 | 
					            rk_parameter const * const last_param = batch->params + batch->nparams;
 | 
				
			||||||
 | 
					            unsigned param_index = 0;
 | 
				
			||||||
            for (rk_command const * command = batch->commands; command < last_command; ++command) {
 | 
					            for (rk_command const * command = batch->commands; command < last_command; ++command) {
 | 
				
			||||||
                for (rk_parameter const * param = batch->params; param < last_param; ++param) {
 | 
					                for (rk_parameter const * param = batch->params; param < last_param; ++param) {
 | 
				
			||||||
                    glBindVertexBuffer(param->binding, batch->params_buffer,
 | 
					                    glBindVertexBuffer(param->binding, batch->params_buffer,
 | 
				
			||||||
                        param->offset + param_index * param->dst_size, param->dst_size);
 | 
					                        param->offset + param_index * param->dst_size, param->dst_size);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            param_index += command->ninstances;
 | 
					 | 
				
			||||||
                glDrawElementsInstanced(
 | 
					                glDrawElementsInstanced(
 | 
				
			||||||
                    GL_TRIANGLES, command->nvertices, GL_UNSIGNED_SHORT,
 | 
					                    GL_TRIANGLES, command->nvertices, GL_UNSIGNED_SHORT,
 | 
				
			||||||
                    reinterpret_cast<void const *>(command->base_index << 1),
 | 
					                    reinterpret_cast<void const *>(command->base_index << 1),
 | 
				
			||||||
                    command->ninstances);
 | 
					                    command->ninstances);
 | 
				
			||||||
 | 
					                param_index += command->ninstances;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    glBindVertexArray(0);
 | 
					    glBindVertexArray(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user