Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-06-07 12:58:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-06-07 13:02:42 +0300
commitcdbda1c3d8017b994366b101b34c79a5df58902f (patch)
tree8b2f18917c0fb847629af39233e1c20e0739caaf /source/blender/gpu/intern/gpu_material.c
parent366ac88d685d569e5eaa19ce3fc43764683b60fd (diff)
GPUPass: Refactor gpupass caching system to allow fast gpumaterial creation.
This is part of the work needed to refactor the material parameters update. Now the gpupass cache is polled before adding the gpumaterial to the deferred compilation queue. We store gpupasses in a single linked list grouped based on their hashes. This is not the most efficient way but it can be improved upon later.
Diffstat (limited to 'source/blender/gpu/intern/gpu_material.c')
-rw-r--r--source/blender/gpu/intern/gpu_material.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 7b3750c970b..96c321f9107 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -602,7 +602,8 @@ GPUMaterial *GPU_material_from_nodetree_find(
* so only do this when they are needed.
*/
GPUMaterial *GPU_material_from_nodetree(
- Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options)
+ Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
{
LinkData *link;
bool has_volume_output, has_surface_output;
@@ -631,11 +632,38 @@ GPUMaterial *GPU_material_from_nodetree(
* generated VBOs are ready to accept the future shader. */
GPU_nodes_prune(&mat->nodes, mat->outlink);
GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
- mat->status = GPU_MAT_QUEUED;
+ /* Create source code and search pass cache for an already compiled version. */
+ mat->pass = GPU_generate_pass_new(mat,
+ mat->outlink,
+ &mat->attribs,
+ &mat->nodes,
+ vert_code,
+ geom_code,
+ frag_lib,
+ defines);
+
+ if (mat->pass == NULL) {
+ /* We had a cache hit and the shader has already failed to compile. */
+ mat->status = GPU_MAT_FAILED;
+ }
+ else {
+ GPUShader *sh = GPU_pass_shader_get(mat->pass);
+ if (sh != NULL) {
+ /* We had a cache hit and the shader is already compiled. */
+ mat->status = GPU_MAT_SUCCESS;
+ GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes);
+ }
+ else {
+ mat->status = GPU_MAT_QUEUED;
+ }
+ }
+ }
+ else {
+ mat->status = GPU_MAT_FAILED;
}
/* note that even if building the shader fails in some way, we still keep
- * it to avoid trying to compile again and again, and simple do not use
+ * it to avoid trying to compile again and again, and simply do not use
* the actual shader on drawing */
link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
@@ -645,17 +673,26 @@ GPUMaterial *GPU_material_from_nodetree(
return mat;
}
-void GPU_material_generate_pass(
- GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+void GPU_material_compile(GPUMaterial *mat)
{
- BLI_assert(mat->pass == NULL); /* Only run once! */
- if (mat->outlink) {
- mat->pass = GPU_generate_pass_new(
- mat, mat->outlink, &mat->attribs, &mat->nodes, &mat->inputs, vert_code, geom_code, frag_lib, defines);
- mat->status = (mat->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
+ /* Only run once! */
+ BLI_assert(mat->status == GPU_MAT_QUEUED);
+ BLI_assert(mat->pass);
+
+ /* NOTE: The shader may have already been compiled here since we are
+ * sharing GPUShader across GPUMaterials. In this case it's a no-op. */
+ GPU_pass_compile(mat->pass);
+ GPUShader *sh = GPU_pass_shader_get(mat->pass);
+
+ if (sh != NULL) {
+ mat->status = GPU_MAT_SUCCESS;
+ GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes);
}
else {
mat->status = GPU_MAT_FAILED;
+ GPU_pass_free_nodes(&mat->nodes);
+ GPU_pass_release(mat->pass);
+ mat->pass = NULL;
}
}