66import com .jme3 .light .Light ;
77import com .jme3 .light .PointLight ;
88import com .jme3 .light .SpotLight ;
9+ import com .jme3 .material .Material ;
910import com .jme3 .material .RenderState ;
1011import com .jme3 .material .plugins .VulkanMaterialLoader ;
1112import com .jme3 .math .ColorRGBA ;
5354import com .jme3 .vulkan .material .NewMaterialDef ;
5455import com .jme3 .vulkan .material .VulkanMaterial ;
5556import com .jme3 .vulkan .material .shader .ShaderModule ;
57+ import com .jme3 .vulkan .material .technique .NewTechnique ;
58+ import com .jme3 .vulkan .material .technique .VulkanTechnique ;
5659import com .jme3 .vulkan .material .uniforms .TextureUniform ;
5760import com .jme3 .vulkan .material .uniforms .Uniform ;
5861import com .jme3 .vulkan .material .uniforms .StructUniform ;
5962import com .jme3 .vulkan .memory .MemoryProp ;
6063import com .jme3 .vulkan .memory .MemorySize ;
61- import com .jme3 .vulkan .mesh .AdaptiveMesh ;
62- import com .jme3 .vulkan .mesh .AdaptiveVertexBinding ;
63- import com .jme3 .vulkan .mesh .InputRate ;
64- import com .jme3 .vulkan .mesh .MeshLayout ;
64+ import com .jme3 .vulkan .mesh .*;
6565import com .jme3 .vulkan .mesh .attribute .*;
6666import com .jme3 .vulkan .pass .Attachment ;
6767import com .jme3 .vulkan .pass .RenderPass ;
7171import com .jme3 .vulkan .pipeline .framebuffer .FrameBuffer ;
7272import com .jme3 .vulkan .pipeline .framebuffer .OutputFrameBuffer ;
7373import com .jme3 .vulkan .pipeline .graphics .GraphicsPipeline ;
74+ import com .jme3 .vulkan .render .AbstractBatchElement ;
7475import com .jme3 .vulkan .render .GeometryBatch ;
7576import com .jme3 .vulkan .render .RenderEngine ;
7677import com .jme3 .vulkan .render .VulkanGeometryBatch ;
@@ -172,7 +173,11 @@ public static class Transforms implements Struct {
172173 private OutputFrameBuffer outFrameBuffer ;
173174 private final BufferGenerator <VulkanBuffer > bufferGen = new BufferGeneratorImpl ();
174175
175- private VulkanGeometryBatch opaque , sky , transparent , gui , translucent ;
176+ private final GeometryBatch <Element > opaque = new GeometryBatch <>(new OpaqueComparator ());
177+ private final GeometryBatch <Element > sky = new GeometryBatch <>(new OpaqueComparator ());
178+ private final GeometryBatch <Element > transparent = new GeometryBatch <>(new TransparentComparator ());
179+ private final GeometryBatch <Element > gui = new GeometryBatch <>(new GuiComparator ());
180+ private final GeometryBatch <Element > translucent = new GeometryBatch <>(new TransparentComparator ());
176181
177182 private final Cache <Pipeline > pipelineCache = new Cache <>();
178183 private final Cache <PipelineLayout > pipelineLayoutCache = new Cache <>();
@@ -270,13 +275,7 @@ private void initialize() {
270275 }));
271276 });
272277
273- opaque = new EngineGeometryBatch (new OpaqueComparator (), descriptorPool );
274- sky = new EngineGeometryBatch (new OpaqueComparator (), descriptorPool );
275- transparent = new EngineGeometryBatch (new TransparentComparator (), descriptorPool );
276- gui = new EngineGeometryBatch (new GuiComparator (), descriptorPool );
277- translucent = new EngineGeometryBatch (new TransparentComparator (), descriptorPool );
278278 outFrameBuffer = new OutputFrameBuffer (swapchain , renderPass );
279-
280279 stream = new BufferStream (device , 500 );
281280 for (int i = 0 ; i < framesInFlight .length ; i ++) {
282281 framesInFlight [i ] = new Frame ();
@@ -417,40 +416,38 @@ private void render(ViewPort vp) {
417416 for (Spatial scene : vp .getScenes ()) for (Spatial .GraphIterator it = scene .iterator (cull , bucket ); it .hasNext ();) {
418417 Spatial child = it .next ();
419418 child .runControlRender (SimpleVulkanEngine .this , vp );
420- if (cull .peek () ! = Camera .FrustumIntersect .Outside ) {
421- if ( child instanceof Geometry ) {
422- Geometry g = ( Geometry ) child ;
423- if ( vp . getGeometryFilter () == null || vp . getGeometryFilter (). test ( g )) {
424- GeometryBatch <?> batch = getBatchByQueueBucket ( bucket . peek ());
425- if ( batch != null ) {
426- batch . add ( g );
427- }
419+ if (cull .peek () = = Camera .FrustumIntersect .Outside ) {
420+ it . skipChildren ();
421+ } else if ( child instanceof Geometry ) {
422+ Geometry g = ( Geometry ) child ;
423+ if ( vp . getGeometryFilter () == null || vp . getGeometryFilter (). test ( g )) {
424+ GeometryBatch <?> batch = getBatchByQueueBucket ( bucket . peek ());
425+ if ( batch != null ) {
426+ batch . add ( new Element ( g , null , ));
428427 }
429428 }
430- } else {
431- it .skipChildren ();
432429 }
433430 }
434431
435- CommandSetting <ViewPortArea > vpArea = CommandSetting .viewPort ();
436- CommandSetting <ScissorArea > scissor = CommandSetting .scissor ();
432+ CommandSetting <ViewPortArea > vpArea = graphics . addSetting ( CommandSetting .viewPort () );
433+ CommandSetting <ScissorArea > scissor = graphics . addSetting ( CommandSetting .scissor () );
437434
438435 vpArea .push (vp .getArea ());
439436 scissor .push (vp .getArea ().toScissor (null ));
440437 {
441- opaque . render ( graphics , vpArea , scissor );
438+ renderBatch ( opaque );
442439 vpArea .push (vp .getArea ().clone ().toMaxDepth ());
443440 {
444- sky . render ( graphics , vpArea , scissor );
441+ renderBatch ( sky );
445442 }
446443 vpArea .pop ();
447- transparent . render ( graphics , vpArea , scissor );
444+ renderBatch ( transparent );
448445 vpArea .push (vp .getArea ().clone ().toMinDepth ());
449446 {
450- gui . render ( graphics , vpArea , scissor );
447+ renderBatch ( gui );
451448 }
452449 vpArea .pop ();
453- translucent . render ( graphics , vpArea , scissor );
450+ renderBatch ( translucent );
454451 }
455452 vpArea .pop ();
456453 scissor .pop ();
@@ -464,67 +461,22 @@ private void render(ViewPort vp) {
464461
465462 }
466463
467- private GeometryBatch <?> getBatchByQueueBucket (RenderQueue .Bucket bucket ) {
468- switch (bucket ) {
469- case Opaque : return opaque ;
470- case Sky : return sky ;
471- case Transparent : return transparent ;
472- case Gui : return gui ;
473- case Translucent : return translucent ;
474- default : return null ;
475- }
476- }
477-
478- }
479-
480- private class EngineGeometryBatch extends VulkanGeometryBatch {
481-
482- private final RenderState tempState = new RenderState ();
483-
484- public EngineGeometryBatch (Comparator <? super Element > comparator , DescriptorPool pool ) {
485- super (comparator , pool );
486- }
487-
488- @ Override
489- protected VertexPipeline createPipeline (Element e ) {
490- return GraphicsPipeline .build (device , p -> {
491- p .setCache (pipelineCache );
492- p .setLayoutCache (pipelineLayoutCache );
493- p .setShaderCache (shaderCache );
494- p .setSetLayoutCache (descSetLayoutCache );
495- p .setSubpass (renderPass .getSubpass (0 ));
496- p .setDynamic (DynamicState .ViewPort , true );
497- p .setDynamic (DynamicState .Scissor , true );
498- p .setDepthClamp (true );
499- p .applyGeometry (app .getAssetManager (), e .getMesh (), e .getMaterial (), e .getTechnique ());
500- p .applyRenderState (tempState .integrateGeometryStates (e .getGeometry (), forcedRenderState ,
501- e .getMaterial ().getAdditionalRenderState (), e .getTechnique ().getRenderState ()));
502- });
503- }
504-
505- @ Override
506- public void render (CommandBuffer cmd , Runnable onRender ) {
507- if (onRender != null && !queue .isEmpty ()) {
508- onRender .run ();
464+ private void renderBatch (GeometryBatch <Element > batch ) {
465+ if (batch .isEmpty ()) {
466+ return ;
509467 }
510- transforms . viewProjectionMatrix . set ( camera . getViewProjectionMatrix () );
468+ graphics . applySettings ( );
511469 VertexPipeline currentPipeline = null ;
512470 VulkanMaterial currentMaterial = null ;
513471 TempVars vars = TempVars .get ();
514- for (Element e : queue ) {
515-
516- // bind pipeline if necessary
472+ for (Element e : batch ) {
517473 if (e .getPipeline () != currentPipeline ) {
518- (currentPipeline = e .getPipeline ()).bind (cmd );
474+ (currentPipeline = e .getPipeline ()).bind (graphics );
519475 currentMaterial = null ;
520476 }
521-
522- // bind material if necessary
523477 if (e .getMaterial () != currentMaterial ) {
524- (currentMaterial = e .getMaterial ()).bind (cmd , currentPipeline , descriptorPool );
478+ (currentMaterial = e .getMaterial ()).bind (graphics , currentPipeline , descriptorPool );
525479 }
526-
527- // find light indices
528480 lighting .indices .clear ();
529481 int lightIndex = 0 ;
530482 for (LightData l : lighting .lights ) {
@@ -533,17 +485,26 @@ public void render(CommandBuffer cmd, Runnable onRender) {
533485 }
534486 lightIndex ++;
535487 }
536-
537488 transforms .viewProjectionMatrix .mult (e .getGeometry ().getWorldMatrix (), transforms .worldViewProjectionMatrix );
538489 currentMaterial .set ("Lighting" , lighting );
539490 currentMaterial .set ("Transforms" , transforms );
540- stream .stream (cmd );
541-
542- // render
543- e .getMesh ().render (cmd , currentPipeline );
491+ stream .stream (graphics ); // this is a problem
492+ e .getMesh ().render (graphics , e .getPipeline ());
544493 }
545494 vars .release ();
546495 }
496+
497+ private GeometryBatch <?> getBatchByQueueBucket (RenderQueue .Bucket bucket ) {
498+ switch (bucket ) {
499+ case Opaque : return opaque ;
500+ case Sky : return sky ;
501+ case Transparent : return transparent ;
502+ case Gui : return gui ;
503+ case Translucent : return translucent ;
504+ default : return null ;
505+ }
506+ }
507+
547508 }
548509
549510 private class SwapchainUpdater implements Consumer <Swapchain > {
@@ -584,4 +545,75 @@ public VulkanBuffer createBuffer(MemorySize size, Flag<BufferUsage> bufUsage, Gl
584545
585546 }
586547
548+ private class Element extends AbstractBatchElement {
549+
550+ private final VulkanTechnique technique ;
551+ private final VulkanMaterial material ;
552+ private final VulkanMesh mesh ;
553+ private final VertexPipeline pipeline ;
554+
555+ private Element (Geometry geometry , RenderState forcedRenderState ,
556+ Material forcedMaterial , String forcedTechnique , Mesh forcedMesh ) {
557+ super (geometry );
558+ Material mat = forcedMaterial != null ? forcedMaterial : geometry .getMaterial ();
559+ if (!(mat instanceof NewMaterial )) {
560+ throw new ClassCastException ("Cannot render " + mat .getClass () + " in a Vulkan context." );
561+ }
562+ this .material = (VulkanMaterial )mat ;
563+ this .technique = material .getTechnique (forcedTechnique != null ? forcedTechnique : "main" );
564+ Mesh mesh = forcedMesh != null ? forcedMesh : geometry .getMesh ();
565+ if (!(mesh instanceof VulkanMesh )) {
566+ throw new ClassCastException ("Cannot render " + mesh .getClass () + " in a Vulkan context." );
567+ }
568+ this .mesh = (VulkanMesh )mesh ;
569+ this .pipeline = GraphicsPipeline .build (device , p -> {
570+ p .setCache (pipelineCache );
571+ p .setLayoutCache (pipelineLayoutCache );
572+ p .setShaderCache (shaderCache );
573+ p .setSetLayoutCache (descSetLayoutCache );
574+ p .setSubpass (renderPass .getSubpass (0 ));
575+ p .setDynamic (DynamicState .ViewPort , true );
576+ p .setDynamic (DynamicState .Scissor , true );
577+ p .setDepthClamp (true );
578+ p .applyGeometry (app .getAssetManager (), this .mesh , this .material , this .technique );
579+ p .applyRenderState (new RenderState ().integrateGeometryStates (geometry , forcedRenderState ,
580+ this .material .getAdditionalRenderState (), this .technique .getRenderState ()));
581+ });
582+ }
583+
584+ @ Override
585+ public Camera getCamera () {
586+ return VulkanGeometryBatch .this .getCamera ();
587+ }
588+
589+ @ Override
590+ public VulkanMaterial getMaterial () {
591+ return material ;
592+ }
593+
594+ @ Override
595+ public VulkanMesh getMesh () {
596+ return mesh ;
597+ }
598+
599+ @ Override
600+ public long getPipelineSortId () {
601+ return pipeline .getSortId ();
602+ }
603+
604+ @ Override
605+ public long getMaterialSortId () {
606+ return 0 ;
607+ }
608+
609+ public VulkanTechnique getTechnique () {
610+ return technique ;
611+ }
612+
613+ public VertexPipeline getPipeline () {
614+ return pipeline ;
615+ }
616+
617+ }
618+
587619}
0 commit comments