Replies: 11 comments 16 replies
-
For completeness, this is the log of the typical VK validation-errors that I am getting from this:
|
Beta Was this translation helpful? Give feedback.
-
@drywolf would it be possible to create an example of what you are attempting to do and share this and any necessary data? Ideally in a form that we can add to vsgExamples as a form of unit test/something for us to iterate on to resolve the issue, then later as something others can learn from how to do this type of customization work. As @timoore mentioned he has some mods to the VSG that he uses to do what he requires in vsgCs once this as submitted I'll review these and either merge them as is or do other refactor work to address the problems his changes address. I'll then wrap this up in a stable release. This is how the VSG project evolves, new uses come along and push the VSG beyond it's present capabilities, we refactor or add to it to resolve these deficiencies. Using examples as unit tests is one way I like to use through this process - the example can be written to do something that needs to be done, and perhaps is done way more complicated than desired, or not work at all, then changes to the VSG can be tried out to resolve the issues, then finally we end up with a solution and a nature example. It may of course be that actually it doesn't require any mods to the core VSG, just a little refactor of the example. |
Beta Was this translation helpful? Give feedback.
-
As a general comment, the vsg::SharedObjects class is used to avoid duplicate state from consuming precious memory and CPU/GPU resources. it's a crucial part of getting the best performance out of graphics applications. However, sharing data that will need to be indecently varied can be an issue. The question then is how to be declare which parts are appropriate to share and which should be duplicated. In general you can check the referenceCount of an object to see if it's uniquely held and if it's not cloning the type and assigning the clone to the part that you need to vary will be required, this should just be a local change though, other parts of the scene can still reference the original object that you've cloned. |
Beta Was this translation helpful? Give feedback.
-
I created the minimal vsgExample that shows pretty much exactly what I was trying to do. https://github.com/drywolf/vsgExamples/tree/vsgcustompbr So basically all I did is create a copy of the original I also included in the repository a FBX test-scene that I was using for testing so far (in If you compile & run this example, you will see the validation-errors and get the crash that I mentioned. |
Beta Was this translation helpful? Give feedback.
-
Sorry, I was confusing my aforementioned patches with the current state of vsg and vsgXchange. It's true that the current assumption in vsgXchange is that all descriptors for a pipeline will be bound "at once," and that the descriptor set layout comes from the descriptors that vsgXchange discovers, not from the shader set. |
Beta Was this translation helpful? Give feedback.
-
I have been experimenting with the vsgcustompbr example this morning and see the same Vulkan debug errors. I can remove these errors if I make the additional mat_fx an optional setting and this disables the associated code paths in the fragment shader so avoids the error. but this obviously isn't the intent of vsgcutompbr as it is. The changes I've made include outputting the resulting scene graph so I can reivew the results: diff --git a/data/shaders/standard_pbr_custom.frag b/data/shaders/standard_pbr_custom.frag
index 5521327..9bed068 100644
--- a/data/shaders/standard_pbr_custom.frag
+++ b/data/shaders/standard_pbr_custom.frag
@@ -1,6 +1,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
-#pragma import_defines (VSG_DIFFUSE_MAP, VSG_GREYSACLE_DIFFUSE_MAP, VSG_EMISSIVE_MAP, VSG_LIGHTMAP_MAP, VSG_NORMAL_MAP, VSG_METALLROUGHNESS_MAP, VSG_SPECULAR_MAP, VSG_TWO_SIDED_LIGHTING, VSG_WORKFLOW_SPECGLOSS)
+#pragma import_defines (VSG_DIFFUSE_MAP, VSG_GREYSACLE_DIFFUSE_MAP, VSG_EMISSIVE_MAP, VSG_LIGHTMAP_MAP, VSG_NORMAL_MAP, VSG_METALLROUGHNESS_MAP, VSG_SPECULAR_MAP, VSG_TWO_SIDED_LIGHTING, VSG_WORKFLOW_SPECGLOSS, VSG_MATFXDATA)
+
const float PI = 3.14159265359;
const float RECIPROCAL_PI = 0.31830988618;
@@ -32,10 +33,12 @@ layout(binding = 4) uniform sampler2D emissiveMap;
layout(binding = 5) uniform sampler2D specularMap;
#endif
+#ifdef VSG_MATFXDATA
layout(binding = 9) uniform MatFxData
{
vec4 overlayColor;
} mat_fx;
+#endif
layout(binding = 10) uniform PbrData
{
@@ -470,6 +473,8 @@ void main()
outColor = LINEARtoSRGB(vec4(color, baseColor.a));
+#ifdef VSG_MATFXDATA
// just perform a simple additive blending of the overlayColor on top of the PBR result
outColor.rgb += mat_fx.overlayColor.rgb;
+#endif
}
diff --git a/examples/shading/vsgcustompbr/custom_pbr.cpp b/examples/shading/vsgcustompbr/custom_pbr.cpp
index 5fe1672..ecb4e16 100644
--- a/examples/shading/vsgcustompbr/custom_pbr.cpp
+++ b/examples/shading/vsgcustompbr/custom_pbr.cpp
@@ -71,7 +71,7 @@ vsg::ref_ptr<vsg::ShaderSet> pbr_custom_ShaderSet(vsg::ref_ptr<const vsg::Option
shaderSet->addUniformBinding("aoMap", "VSG_LIGHTMAP_MAP", 0, 3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::vec4Array2D::create(1, 1));
shaderSet->addUniformBinding("emissiveMap", "VSG_EMISSIVE_MAP", 0, 4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::vec4Array2D::create(1, 1));
shaderSet->addUniformBinding("specularMap", "VSG_SPECULAR_MAP", 0, 5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::vec4Array2D::create(1, 1));
- shaderSet->addUniformBinding("mat_fx", "", 0, 9, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::MaterialFxValue::create());
+ shaderSet->addUniformBinding("mat_fx", "VSG_MATFXDATA", 0, 9, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::MaterialFxValue::create());
shaderSet->addUniformBinding("material", "", 0, 10, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::PbrMaterialValue::create());
shaderSet->addUniformBinding("lightData", "", 1, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, vsg::vec4Array::create(64));
diff --git a/examples/shading/vsgcustompbr/vsgcustompbr.cpp b/examples/shading/vsgcustompbr/vsgcustompbr.cpp
index 56d8542..1c0e81e 100644
--- a/examples/shading/vsgcustompbr/vsgcustompbr.cpp
+++ b/examples/shading/vsgcustompbr/vsgcustompbr.cpp
@@ -79,6 +79,8 @@ int main(int argc, char** argv)
options->add(vsgXchange::all::create());
#endif
+ auto outputFilename = arguments.value<vsg::Path>("", "-o");
+
// create an instance of the custom_pbr shader-set
auto custom_pbr_shaderSet = pbr_custom_ShaderSet(options);
assert(custom_pbr_shaderSet != nullptr);
@@ -193,6 +195,13 @@ int main(int argc, char** argv)
else
vsg_scene = group;
+
+ if (outputFilename)
+ {
+ vsg::write(vsg_scene, outputFilename, options);
+ return 1;
+ }
+
// create the viewer and assign window(s) to it
auto viewer = vsg::Viewer::create();
auto window = vsg::Window::create(windowTraits); Adding the #define this way is how the #pragma(tic) shader composition is meant to work, but... as the vsgXchange::assimp plugin doesn't know that it should assign this custom data it doesn't assign and enable the associated code path. This lack of knowledge of the data type is also when the vsgXchange::assimp isn't assigned even the prototype or setting up any of the associated DescriptorSetLayout. My current feeling is the problem lies in how do we inject custom data types/optional shader paths that loaders don't know about. The current vsg::GraphicsPipelineConfigurator will need to evolve further to enable this type of injection, and/or have vsg::Options provide the data to inject. A first step may be to change the vsg::GraphicsPipelineConfigurator to assign all the non option entries and use the default value provided, so I'll look at this next. I currently don't think the vsg::SharedObjects usage is related these particular issues, instead it's an orthogonal issue of how should we handle data that has been shared but we want to control multiple instances of the data rather than a single shared instance. There are solutions for this like the ones I mention in a previous reply, as well as vsg::SharedObjects::suitableForSharing visitor that users can override to prevent sharing of particular types of objects. |
Beta Was this translation helpful? Give feedback.
-
You should take a look at what I do in vsgCs. The change from VSG / vsgXchange is that the pipeline layout is created from the ShaderSet and the defines that are part of shaderHints, which these days usually come from DescriptorConfigurator. I'm preparing a PR which merges the VSG approach into VSG. This should work for the OP if the ShaderSet unconditionally includes the descriptor bindings that they want. I'm not sure what to do if they want to enable it by an option passed to vsgXchange. |
Beta Was this translation helpful? Give feedback.
-
@timoore OK I will wait for the PR before I dive into tweaking vsg::GraphicsPipelineConfiguration & vsgXchange::assimp to avoid diverging things/changing the same code. |
Beta Was this translation helpful? Give feedback.
-
I will continue to poke at the vsgcustompbr example code and let you know if I come across any ideas/solutions for getting this usecase working properly/easily. I am also curious to see how much of the solution already would be in the potential PR coming from the vsgCs code. 👍 |
Beta Was this translation helpful? Give feedback.
-
I think makePipelineLayout() (called by GraphicsPipelineConfigurator::init()) does what you describe? It includes all bindings that are enabled by a define, or that are not optional, up to the requested descriptor set.
|
Beta Was this translation helpful? Give feedback.
-
@drywolf Through this week I have been refactoring vsg::DescriptorConfigurator and vsg::GraphicsPipelineConfigurator to support multiple DescriptorSet, custom of DescriptorSet bindings such as support for vsg::ViewDependentState in an extensible way, and finally to automatically assign descriptors that the ShaderSet specifies that have the define=="" so essentially default parameters that should always be set. All of this work has been carried out in MultiDescriptorSetConfiguration branches of the VSG, vsgXchange, vsgPoints and vsgExamples, and also just wrapped up by getting your vsgcustompbr example working, with just a small change adding in the new ShaderSet::customDescriptorSetBindings functionality, see below for the changes I have made: diff --git a/examples/shading/vsgcustompbr/custom_pbr.cpp b/examples/shading/vsgcustompbr/custom_pbr.cpp
index 5fe1672..3ac05fc 100644
--- a/examples/shading/vsgcustompbr/custom_pbr.cpp
+++ b/examples/shading/vsgcustompbr/custom_pbr.cpp
@@ -85,5 +85,7 @@ vsg::ref_ptr<vsg::ShaderSet> pbr_custom_ShaderSet(vsg::ref_ptr<const vsg::Option
shaderSet->definesArrayStates.push_back(vsg::DefinesArrayState{{"VSG_DISPLACEMENT_MAP"}, vsg::DisplacementMapArrayState::create()});
shaderSet->definesArrayStates.push_back(vsg::DefinesArrayState{{"VSG_BILLBOARD"}, vsg::BillboardArrayState::create()});
+ shaderSet->customDescriptorSetBindings.push_back(vsg::ViewDependentStateBinding::create(1));
+
return shaderSet;
} The branches of interest are: https://github.com/vsg-dev/VulkanSceneGraph/tree/MultiDescriptorSetConfiguration I still have some work dev work/testing to do on these branches but they should be far enough along for others to start testing. I need to go right now, but over the next few days I'll provide a bit more info about this work. |
Beta Was this translation helpful? Give feedback.
-
Hi,
I am loading scenes via vsgXchange, and those scenes might have several mesh-objects, some of which will use Phong-material and others will use PBR-material (in the same scene!)
Now I am trying to use a customized PBR shaderset (while leaving the Phong shaderset untouched)
I added the following uniform buffer to the
standard_pbr.frag
:and I am using
overlayColor
in the shader code to do a simple color-blending on top of the original PBR shader result.To be able to use this modified shader, I copied the code from vsgExamples -> flat.cpp and I am using the path to my modified
.frag
shader file.Also I added the new uniform-binding to this custom shader-set like so:
This shader-set instance I then apply to vsg::Options, when I load the scene via vsgXchange:
This is all good so far, but here comes the problem.
To make this work, I also need to "patch" the
vsg::BindGraphicsPipeline
command-nodes andvsg::BindDescriptorSet
command-nodes that are used when rendering the PBR shader-set in the command-graph.In vsgExamples -> vsgstateswitch.cpp I saw that such modifications to an existing command-graph can be done by using a custom
vsg::Visitor
that will look for the specific node-types and there you can apply the modifications that you need.So I created such a custom visitor, and started patching the necessary Vulkan state to include
binding = 9
vsg::DescriptorSetLayout::bindings
list I insert an extraVkDescriptorSetLayoutBinding
withbinding = 9
vsg::DescriptorSet::descriptors
list I insert an extra uniform-buffer descriptorvsg::DescriptorBuffer::create(mat_fx_data, 9)
This already worked for a simple scene, where I only had a single mesh that was using only the PBR shader.
But when I started doing some tests with more complex scenes, this same code started giving me all kinds of VK validation errors and crashes.
It took a while for me to figure out what was going on.
The problem is happening because:
layout(binding = 9)
for this material type(but this is also kind of what I wanted, I only want the PBR material-type to have this color overlay, the Phong material-type should not need to have any changes, just because I decide to change the PBR material)
As said, at this point in time, I still kept getting VK errors and crashes. I quickly realized that I needed to modify the VK/VSG state only for draw-commands related to PBR meshes (and not change any VK/VSG state related to the Phong draw-commands)
So then I tried to modify my code to only insert the extra
VkDescriptorSetLayoutBinding
andvsg::DescriptorBuffer
in cases where the graphics-pipeline is rendering a PBR mesh.I thought this should be fine now, but I still kept getting the same crashes/validation-errors.
Some more hours of debugging, and I finally realized that
vsg::SharedObjects
was doing things, I didn't expect it to do.(and this is actually what this whole thread should be about)
Basically, when vsgXchange loads the scene, any descriptor-set or descriptor-layout that is created, will be
automagically
de-duplicated byvsg::SharedObjects
.This means that for all draw-commands in the render-graph, if their descriptor-set and/or descriptor-layout are exactly the same (even if it is just by pure coincidence), vsg will silently re-use a single VSG object for all the Vulkan state/commands in the graph.
Now when I do modifications to the render-graph, I can never know if a descriptor-set/descriptor-layout that I am visiting and modifying will only be used for a PBR shader-set drawcall, or also for some Phong shader-set drawcalls 🤯 🙈
Hence when I make the modifications that I intended only for PBR draw-commands, I always also
implicitly
change the Vulkan state for the Phong draw-commands.@robertosfield
Maybe I am trying to do this the wrong way, so please let me know if there is a better solution to use a custom PBR shader-set + add the required VK states to the render-graph.
But also on the other hand, this very
implicit
andhidden
state/object sharing really will be quite confusing and might cause lots of spent hours of debugging, if there is not a really solid & somewhatexplicit
API to handle it.I also would be really interested to hear some of your thoughts on the current design
(maybe you have already written something about it? I'm sorry if I did miss it)
Thanks
PS: I am really a fan of VSG so far ❤️ and I want to dive deeper into it and learn more.
(I did not intend the above to sound harsh or as unfunded criticism ... I just want to understand how I would achieve the thing that I am trying to do)
Beta Was this translation helpful? Give feedback.
All reactions