@@ -108,9 +108,8 @@ vk_gltf_viewer::vulkan::Frame::Frame(std::shared_ptr<const Renderer> _renderer,
108
108
, swapchainImageAcquireSema { sharedData.gpu .device , vk::SemaphoreCreateInfo{} }
109
109
, inFlightFence { sharedData.gpu .device , vk::FenceCreateInfo{} } {
110
110
// Allocate descriptor sets.
111
- std::tie (mousePickingSet, multiNodeMousePickingSet, hoveringNodeJumpFloodSet, selectedNodeJumpFloodSet, hoveringNodeOutlineSet, selectedNodeOutlineSet, weightedBlendedCompositionSet, inverseToneMappingSet, bloomSet, bloomApplySet)
111
+ std::tie (mousePickingSet, hoveringNodeJumpFloodSet, selectedNodeJumpFloodSet, hoveringNodeOutlineSet, selectedNodeOutlineSet, weightedBlendedCompositionSet, inverseToneMappingSet, bloomSet, bloomApplySet)
112
112
= allocateDescriptorSets (*descriptorPool, std::tie (
113
- sharedData.mousePickingRenderPipeline .descriptorSetLayout ,
114
113
sharedData.multiNodeMousePickingDescriptorSetLayout ,
115
114
sharedData.jumpFloodComputePipeline .descriptorSetLayout ,
116
115
sharedData.jumpFloodComputePipeline .descriptorSetLayout ,
@@ -149,9 +148,9 @@ vk_gltf_viewer::vulkan::Frame::ExecutionResult vk_gltf_viewer::vulkan::Frame::ge
149
148
}
150
149
},
151
150
[&](const vk::Offset2D&) {
152
- const std::uint16_t hoveringNodeIndex = gltfAsset->mousePickingResultBuffer .asValue <const std::uint32_t >();
153
- if (hoveringNodeIndex != NO_INDEX) {
154
- result.mousePickingResult .emplace <std::size_t >(hoveringNodeIndex );
151
+ const std::uint32_t packedNodeIndexAndDepth = gltfAsset->mousePickingResultBuffer .asValue <const std::uint32_t >();
152
+ if (std:: uint32_t nodeIndex = packedNodeIndexAndDepth & 0xFFFF ; nodeIndex != NO_INDEX) {
153
+ result.mousePickingResult .emplace <std::size_t >(nodeIndex );
155
154
}
156
155
},
157
156
[](std::monostate) { }
@@ -228,15 +227,15 @@ void vk_gltf_viewer::vulkan::Frame::update(const ExecutionTask &task) {
228
227
if (primitive.materialIndex ) {
229
228
const fastgltf::Material& material = gltfAsset->assetExtended ->asset .materials [*primitive.materialIndex ];
230
229
if (material.alphaMode == fastgltf::AlphaMode::Mask) {
231
- result.pipeline = *sharedData.getMaskPrepassPipelines (primitive).nodeIndexRenderPipeline ;
230
+ result.pipeline = *sharedData.getMaskPrepassPipelines (primitive).nodeMousePickingRenderPipeline ;
232
231
}
233
232
else {
234
- result.pipeline = *sharedData.getPrepassPipelines (primitive).nodeIndexRenderPipeline ;
233
+ result.pipeline = *sharedData.getPrepassPipelines (primitive).nodeMousePickingRenderPipeline ;
235
234
}
236
235
result.cullMode = material.doubleSided ? vk::CullModeFlagBits::eNone : vk::CullModeFlagBits::eBack;
237
236
}
238
237
else {
239
- result.pipeline = *sharedData.getPrepassPipelines (primitive).nodeIndexRenderPipeline ;
238
+ result.pipeline = *sharedData.getPrepassPipelines (primitive).nodeMousePickingRenderPipeline ;
240
239
}
241
240
return result;
242
241
};
@@ -863,7 +862,6 @@ void vk_gltf_viewer::vulkan::Frame::setPassthruExtent(const vk::Extent2D &extent
863
862
}
864
863
865
864
sharedData.gpu .device .updateDescriptorSets ({
866
- mousePickingSet.getWriteOne <0 >({ {}, *passthruResources->mousePickingAttachmentGroup .getColorAttachment (0 ).view , vk::ImageLayout::eShaderReadOnlyOptimal }),
867
865
hoveringNodeJumpFloodSet.getWriteOne <0 >({ {}, *passthruResources->hoveringNodeOutlineJumpFloodResources .imageView , vk::ImageLayout::eGeneral }),
868
866
selectedNodeJumpFloodSet.getWriteOne <0 >({ {}, *passthruResources->selectedNodeOutlineJumpFloodResources .imageView , vk::ImageLayout::eGeneral }),
869
867
weightedBlendedCompositionSet.getWrite <0 >(vku::unsafeProxy ({
@@ -916,8 +914,7 @@ void vk_gltf_viewer::vulkan::Frame::updateAsset() {
916
914
917
915
// Update the descriptors that are unrelated to the asset textures.
918
916
sharedData.gpu .device .updateDescriptorSets ({
919
- mousePickingSet.getWriteOne <1 >({ inner.mousePickingResultBuffer , 0 , sizeof (std::uint32_t ) }),
920
- multiNodeMousePickingSet.getWriteOne <0 >({ inner.mousePickingResultBuffer , 0 , vk::WholeSize }),
917
+ mousePickingSet.getWriteOne <0 >({ inner.mousePickingResultBuffer , 0 , vk::WholeSize }),
921
918
assetDescriptorSet.getWrite <0 >(inner.assetExtended ->primitiveBuffer .descriptorInfo ),
922
919
assetDescriptorSet.getWrite <1 >(inner.nodeBuffer .descriptorInfo ),
923
920
assetDescriptorSet.getWrite <2 >(inner.assetExtended ->materialBuffer .descriptorInfo ),
@@ -1023,15 +1020,6 @@ vk_gltf_viewer::vulkan::Frame::PassthruResources::PassthruResources(
1023
1020
vk::CommandBuffer graphicsCommandBuffer
1024
1021
) : extent { extent },
1025
1022
mousePickingAttachmentGroup { sharedData.gpu , extent },
1026
- mousePickingFramebuffer { sharedData.gpu .device , vk::FramebufferCreateInfo {
1027
- {},
1028
- *sharedData.mousePickingRenderPass ,
1029
- vku::unsafeProxy ({
1030
- *mousePickingAttachmentGroup.getColorAttachment (0 ).view ,
1031
- *mousePickingAttachmentGroup.depthStencilAttachment ->view ,
1032
- }),
1033
- extent.width , extent.height , 1 ,
1034
- } },
1035
1023
hoveringNodeOutlineJumpFloodResources { sharedData.gpu , extent },
1036
1024
hoveringNodeJumpFloodSeedAttachmentGroup { sharedData.gpu , hoveringNodeOutlineJumpFloodResources.image },
1037
1025
selectedNodeOutlineJumpFloodResources { sharedData.gpu , extent },
@@ -1118,8 +1106,7 @@ vk_gltf_viewer::vulkan::Frame::PassthruResources::PassthruResources(
1118
1106
1119
1107
vk::raii::DescriptorPool vk_gltf_viewer::vulkan::Frame::createDescriptorPool () const {
1120
1108
const vku::PoolSizes poolSizes
1121
- = sharedData.mousePickingRenderPipeline .descriptorSetLayout .getPoolSize ()
1122
- + sharedData.multiNodeMousePickingDescriptorSetLayout .getPoolSize ()
1109
+ = sharedData.multiNodeMousePickingDescriptorSetLayout .getPoolSize ()
1123
1110
+ 2 * getPoolSizes (sharedData.jumpFloodComputePipeline .descriptorSetLayout , sharedData.outlineRenderPipeline .descriptorSetLayout )
1124
1111
+ sharedData.weightedBlendedCompositionRenderPipeline .descriptorSetLayout .getPoolSize ()
1125
1112
+ sharedData.inverseToneMappingRenderPipeline .descriptorSetLayout .getPoolSize ()
@@ -1130,39 +1117,30 @@ vk::raii::DescriptorPool vk_gltf_viewer::vulkan::Frame::createDescriptorPool() c
1130
1117
}
1131
1118
1132
1119
void vk_gltf_viewer::vulkan::Frame::recordScenePrepassCommands (vk::CommandBuffer cb) const {
1133
- boost::container::static_vector<vk::ImageMemoryBarrier, 3 > memoryBarriers;
1134
-
1135
- // If glTF Scene have to be rendered, prepare attachment layout transition for node index and depth rendering.
1136
- if (renderingNodes) {
1137
- memoryBarriers.push_back ({
1138
- {}, vk::AccessFlagBits::eColorAttachmentWrite,
1139
- {}, vk::ImageLayout::eColorAttachmentOptimal,
1140
- vk::QueueFamilyIgnored, vk::QueueFamilyIgnored,
1141
- passthruResources->mousePickingAttachmentGroup .getColorAttachment (0 ).image , vku::fullSubresourceRange (),
1142
- });
1143
- }
1144
-
1145
- // If hovering node's outline have to be rendered, prepare attachment layout transition for jump flood seeding.
1146
- const auto getJumpFloodSeedImageMemoryBarrier = [](vk::Image image) -> vk::ImageMemoryBarrier {
1120
+ // If hovering/selected node's outline have to be rendered, prepare attachment layout transition for jump flood seeding.
1121
+ constexpr auto getJumpFloodSeedImageMemoryBarrier = [](vk::Image image) -> vk::ImageMemoryBarrier {
1147
1122
return {
1148
1123
{}, vk::AccessFlagBits::eColorAttachmentWrite,
1149
1124
{}, vk::ImageLayout::eColorAttachmentOptimal,
1150
1125
vk::QueueFamilyIgnored, vk::QueueFamilyIgnored,
1151
1126
image, { vk::ImageAspectFlagBits::eColor, 0 , 1 , 0 , 1 } /* ping image */ ,
1152
1127
};
1153
1128
};
1129
+
1130
+ boost::container::static_vector<vk::ImageMemoryBarrier, 2 > memoryBarriers;
1154
1131
if (selectedNodes) {
1155
1132
memoryBarriers.push_back (getJumpFloodSeedImageMemoryBarrier (passthruResources->selectedNodeOutlineJumpFloodResources .image ));
1156
1133
}
1157
- // Same holds for hovering nodes' outline.
1158
1134
if (hoveringNode) {
1159
1135
memoryBarriers.push_back (getJumpFloodSeedImageMemoryBarrier (passthruResources->hoveringNodeOutlineJumpFloodResources .image ));
1160
1136
}
1161
1137
1162
- // Attachment layout transitions.
1163
- cb.pipelineBarrier (
1164
- vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput,
1165
- {}, {}, {}, memoryBarriers);
1138
+ if (!memoryBarriers.empty ()) {
1139
+ // Attachment layout transitions.
1140
+ cb.pipelineBarrier (
1141
+ vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput,
1142
+ {}, {}, {}, memoryBarriers);
1143
+ }
1166
1144
1167
1145
struct ResourceBindingState {
1168
1146
vk::Pipeline pipeline{};
@@ -1236,8 +1214,7 @@ void vk_gltf_viewer::vulkan::Frame::recordScenePrepassCommands(vk::CommandBuffer
1236
1214
// Mouse picking.
1237
1215
const bool makeMousePickingResultBufferAvailableToHost = renderingNodes && visit (multilambda {
1238
1216
[&](const vk::Offset2D &offset) {
1239
- // Clear the first [0, 4] region of mousePickingResultBuffer as NO_INDEX.
1240
- cb.fillBuffer (gltfAsset->mousePickingResultBuffer , 0 , sizeof (std::uint32_t ), NO_INDEX);
1217
+ cb.updateBuffer <std::uint32_t >(gltfAsset->mousePickingResultBuffer , 0 , NO_INDEX);
1241
1218
1242
1219
if (renderingNodes->startMousePickingRenderPass ) {
1243
1220
cb.pipelineBarrier (
@@ -1246,27 +1223,59 @@ void vk_gltf_viewer::vulkan::Frame::recordScenePrepassCommands(vk::CommandBuffer
1246
1223
1247
1224
cb.setScissor (0 , vk::Rect2D { offset, { 1 , 1 } });
1248
1225
1249
- cb.beginRenderPass (vk::RenderPassBeginInfo {
1250
- *sharedData.mousePickingRenderPass ,
1251
- *passthruResources->mousePickingFramebuffer ,
1252
- { { 0 , 0 }, passthruResources->extent },
1253
- vku::unsafeProxy<vk::ClearValue>({
1254
- vk::ClearColorValue { static_cast <std::uint32_t >(NO_INDEX), 0U , 0U , 0U },
1255
- vk::ClearDepthStencilValue { 0 .f , 0U },
1256
- }),
1257
- }, vk::SubpassContents::eInline);
1226
+ auto drawPrimitives = [&, resourceBindingState = ResourceBindingState{}](const auto &indirectDrawCommandBuffers) mutable {
1227
+ for (const auto &[criteria, indirectDrawCommandBuffer] : indirectDrawCommandBuffers) {
1228
+ if (resourceBindingState.pipeline != criteria.pipeline ) {
1229
+ cb.bindPipeline (vk::PipelineBindPoint::eGraphics, resourceBindingState.pipeline = criteria.pipeline );
1230
+ }
1258
1231
1259
- // Subpass 1: draw node index to the 1x1 pixel (which lies at the right below the cursor).
1260
- drawPrimitives (renderingNodes->mousePickingIndirectDrawCommandBuffers );
1232
+ if (!resourceBindingState.descriptorSetBound ) {
1233
+ cb.bindDescriptorSets (vk::PipelineBindPoint::eGraphics, *sharedData.mousePickingPipelineLayout ,
1234
+ 0 , { assetDescriptorSet, mousePickingSet }, {});
1235
+ resourceBindingState.descriptorSetBound = true ;
1236
+ }
1261
1237
1262
- cb.nextSubpass (vk::SubpassContents::eInline);
1238
+ if (!resourceBindingState.pushConstantBound ) {
1239
+ cb.pushConstants <pl::MousePicking::PushConstant>(*sharedData.mousePickingPipelineLayout , vk::ShaderStageFlagBits::eVertex,
1240
+ 0 , pl::MousePicking::PushConstant {
1241
+ .projectionView = projectionViewMatrix,
1242
+ });
1243
+ resourceBindingState.pushConstantBound = true ;
1244
+ }
1245
+
1246
+ if (resourceBindingState.primitiveTopology != criteria.primitiveTopology ) {
1247
+ cb.setPrimitiveTopologyEXT (resourceBindingState.primitiveTopology .emplace (criteria.primitiveTopology ));
1248
+ }
1263
1249
1264
- // Subpass 2: read it and copy to the mousePickingResultBuffer.
1265
- cb.bindPipeline (vk::PipelineBindPoint::eGraphics, *sharedData.mousePickingRenderPipeline .pipeline );
1266
- cb.bindDescriptorSets (vk::PipelineBindPoint::eGraphics, *sharedData.mousePickingRenderPipeline .pipelineLayout , 0 , mousePickingSet, {});
1267
- cb.draw (3 , 1 , 0 , 0 );
1250
+ if (resourceBindingState.cullMode != criteria.cullMode ) {
1251
+ cb.setCullModeEXT (resourceBindingState.cullMode .emplace (criteria.cullMode ));
1252
+ }
1253
+
1254
+ if (criteria.indexType && resourceBindingState.indexType != *criteria.indexType ) {
1255
+ resourceBindingState.indexType .emplace (*criteria.indexType );
1256
+ cb.bindIndexBuffer (
1257
+ gltfAsset->assetExtended ->combinedIndexBuffer ,
1258
+ gltfAsset->assetExtended ->combinedIndexBuffer .getIndexOffsetAndSize (*resourceBindingState.indexType ).first ,
1259
+ *resourceBindingState.indexType );
1260
+ }
1261
+ indirectDrawCommandBuffer.recordDrawCommand (cb, sharedData.gpu .supportDrawIndirectCount );
1262
+ }
1263
+ };
1268
1264
1269
- cb.endRenderPass ();
1265
+ cb.beginRenderingKHR (vk::RenderingInfo {
1266
+ {},
1267
+ { offset, { 1 , 1 } },
1268
+ 1 ,
1269
+ 0 ,
1270
+ vk::ArrayProxyNoTemporaries<const vk::RenderingAttachmentInfo>{},
1271
+ vku::unsafeAddress (vk::RenderingAttachmentInfo {
1272
+ *passthruResources->mousePickingAttachmentGroup .depthStencilAttachment ->view , vk::ImageLayout::eDepthAttachmentOptimal,
1273
+ {}, {}, {},
1274
+ vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eDontCare, vk::ClearDepthStencilValue { 0 .f , 0U },
1275
+ }),
1276
+ });
1277
+ drawPrimitives (renderingNodes->mousePickingIndirectDrawCommandBuffers );
1278
+ cb.endRenderingKHR ();
1270
1279
1271
1280
return true ;
1272
1281
}
@@ -1298,14 +1307,14 @@ void vk_gltf_viewer::vulkan::Frame::recordScenePrepassCommands(vk::CommandBuffer
1298
1307
}
1299
1308
1300
1309
if (!resourceBindingState.descriptorSetBound ) {
1301
- cb.bindDescriptorSets (vk::PipelineBindPoint::eGraphics, *sharedData.multiNodeMousePickingPipelineLayout ,
1302
- 0 , { assetDescriptorSet, multiNodeMousePickingSet }, {});
1310
+ cb.bindDescriptorSets (vk::PipelineBindPoint::eGraphics, *sharedData.mousePickingPipelineLayout ,
1311
+ 0 , { assetDescriptorSet, mousePickingSet }, {});
1303
1312
resourceBindingState.descriptorSetBound = true ;
1304
1313
}
1305
1314
1306
1315
if (!resourceBindingState.pushConstantBound ) {
1307
- cb.pushConstants <pl::MultiNodeMousePicking ::PushConstant>(*sharedData.multiNodeMousePickingPipelineLayout , vk::ShaderStageFlagBits::eVertex,
1308
- 0 , pl::MultiNodeMousePicking ::PushConstant {
1316
+ cb.pushConstants <pl::MousePicking ::PushConstant>(*sharedData.mousePickingPipelineLayout , vk::ShaderStageFlagBits::eVertex,
1317
+ 0 , pl::MousePicking ::PushConstant {
1309
1318
.projectionView = projectionViewMatrix,
1310
1319
});
1311
1320
resourceBindingState.pushConstantBound = true ;
0 commit comments