Skip to content

Commit 0a6c19a

Browse files
committed
create new memory interaction api
1 parent de02b94 commit 0a6c19a

131 files changed

Lines changed: 3169 additions & 1451 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

VulkanDesign.txt

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11

2-
Here is my plan for the material system:
2+
Rendering functionality that should be compatible with all backends are:
33

4-
Unlike jme3, where all uniform bindings were localized to a material, jme4 will allow anything to bind anything to any set/binding. Processes are expected to handle their own descriptor sets for this. This assumes that the relevant processes know exactly what protocol any given shader is following, so there are opportunities for uncoordination here. Luckily, there are a few things going in our favor:
5-
6-
1. Renderers are more or less expected to be handcrafted. If you want to use a shader with a different protocol, you must also design the infrastructure to properly interface with your shader.
7-
2. If a shader doesn't use a particular binding that is supplied, it just doesn't use it. We don't have to check if the shader is actually using it. This is big for general global stuff that gets bound maybe once per frame.
8-
9-
For api, I'm planning on having a ShaderBinding interface, which specifies one or more bindings and exposes UniformBindings that parameters are submitted to. ShaderBinding objects will be created by the Engine, as vulkan and opengl engines will very likely use different implementations. The UniformBinding objects are a bit stickier though, as for vulkan they spawn the writers that interface directly with vulkan. For OpenGL, same thing but with OpenGL.
4+
* Render viewport
5+
* location: anywhere
6+
* Technique implementation
7+
* Specify render state
8+
* shaders (technique)
9+
* macro definitions (material, technique)
10+
* shader binding sets (engine, technique)
11+
* translation from set/binding to binding required for opengl
12+
* attribute locations (shader reflection)
13+
* topology (mesh)
14+
* primitive restart (mesh)
15+
* depth test (material, technique)
16+
* depth write (material, technique)
17+
* depth bounds test (material, technique)
18+
* stencil test (material, technique)
19+
* depth compare (material, technique)
20+
* polygon mode (material, technique)
21+
* cull mode (material, technique)
22+
* face winding (mesh)
23+
* line width (material, technique)
24+
* rasterizer discard (material, technique)
25+
* depth bias (material, technique)
26+
* slope
27+
* constant
28+
* rasterization samples (framebuffer)
29+
* blending (framebuffer, material, technique)
30+
* logic
31+
* blend attachments

gradle/libs.versions.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ lwjgl3-openvr = { module = "org.lwjgl:lwjgl-openvr", version.ref = "lwjgl3"
3636
lwjgl3-ovr = { module = "org.lwjgl:lwjgl-ovr", version.ref = "lwjgl3" }
3737
lwjgl3-vulkan = { module = "org.lwjgl:lwjgl-vulkan", version.ref = "lwjgl3" }
3838
lwjgl3-shaderc = { module = "org.lwjgl:lwjgl-shaderc", version.ref = "lwjgl3" }
39-
lwjgl3-spvc = { module = "org.lwjgl:lwjgl-spvc", version.ref = "lwjgl3" }
39+
lwjgl3-spvc = { module = "org.lwjgl:lwjgl-spvc", version.ref = "lwjgl3" }
40+
lwjgl3-vma = { module = "org.lwjgl:lwjgl-vma", version.ref = "lwjgl3" }
4041

4142
mokito-core = "org.mockito:mockito-core:3.12.4"
4243

jme3-core/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434
api libs.lwjgl3.vulkan
3535
api libs.lwjgl3.shaderc
3636
api libs.lwjgl3.spvc
37+
api libs.lwjgl3.vma
3738

3839
// include natives
3940
runtimeOnly(variantOf(libs.lwjgl3.base){ classifier('natives-windows') })
@@ -74,9 +75,11 @@ dependencies {
7475
//runtimeOnly(variantOf(libs.lwjgl3.vulkan) { classifier('natives-linux') })
7576
runtimeOnly(variantOf(libs.lwjgl3.shaderc){ classifier('natives-linux') })
7677
runtimeOnly(variantOf(libs.lwjgl3.spvc){ classifier('natives-linux') })
78+
runtimeOnly(variantOf(libs.lwjgl3.vma){ classifier('natives-linux') })
7779

7880
// for parsing yaml files
7981
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.1")
82+
implementation("com.github.ben-manes.caffeine:caffeine:2.9.3") // latest version compatible with java 8
8083

8184
}
8285

jme3-core/src/main/java/com/jme3/app/BasicProfilerState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import com.jme3.scene.Mesh;
4646
import com.jme3.scene.Node;
4747
import com.jme3.vulkan.JmePlatform;
48-
import com.jme3.vulkan.buffers.BufferMapping;
48+
import com.jme3.vulkan.buffers.mapping.BufferMapping;
4949
import com.jme3.vulkan.buffers.BufferUsage;
5050
import com.jme3.vulkan.buffers.IdxBuffer;
5151
import com.jme3.vulkan.buffers.saving.UpdateHint;
Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
11

22
package com.jme3.backend;
33

4+
import com.jme3.vulkan.buffers.BufferUsage;
5+
import com.jme3.vulkan.buffers.MappableBuffer;
6+
import com.jme3.vulkan.buffers.saving.UpdateHint;
7+
import com.jme3.vulkan.descriptors.UniformBinding;
48
import com.jme3.vulkan.material.exp2.RenderSession;
5-
import com.jme3.vulkan.material.experimental.FrameRenderer;
69
import com.jme3.vulkan.material.experimental.ShaderBindingSet;
7-
import com.jme3.vulkan.material.experimental.ShaderSetBuilder;
10+
import com.jme3.vulkan.material.shader.ShaderModule;
11+
import com.jme3.vulkan.material.shader.ShaderStage;
12+
import com.jme3.vulkan.slang.ComponentType;
13+
import com.jme3.vulkan.slang.Session;
14+
import com.jme3.vulkan.util.Flag;
815

9-
import java.util.function.Consumer;
16+
import java.util.Map;
1017

1118
public interface Engine {
1219

13-
/**
14-
* Creates a {@link FrameRenderer} for performing rendering tasks for the current rendering frame.
15-
*
16-
* @param tpf time per frame
17-
* @return renderer
18-
*/
1920
RenderSession createRenderSession(float tpf);
2021

21-
ShadingLayout createShadingLayout()
22+
MappableBuffer createBuffer(long bytes, Flag<BufferUsage> usage, UpdateHint update);
2223

23-
ShaderBindingSet createShaderBindings(Consumer<ShaderSetBuilder> builder);
24+
ShaderBindingSet createShaderSet(Map<Integer, UniformBinding> bindings);
25+
26+
UniformBinding createUniformBufferBinding(Flag<ShaderStage> scope);
27+
28+
UniformBinding createStorageBufferBinding(Flag<ShaderStage> scope);
29+
30+
UniformBinding createTextureBinding(Flag<ShaderStage> scope);
31+
32+
ShaderModule createShader(ComponentType component);
33+
34+
Session getSlangSession();
2435

2536
}

jme3-core/src/main/java/com/jme3/backend/SimpleVulkanEngine.java

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.jme3.app.Application;
44
import com.jme3.material.plugins.VulkanMaterialLoader;
5+
import com.jme3.renderer.Camera;
56
import com.jme3.renderer.ViewPort;
67
import com.jme3.renderer.queue.OpaqueComparator;
78
import com.jme3.renderer.queue.TransparentComparator;
@@ -27,10 +28,12 @@
2728
import com.jme3.vulkan.material.shader.ShaderStage;
2829
import com.jme3.vulkan.memory.MemoryProp;
2930
import com.jme3.vulkan.pipeline.*;
30-
import com.jme3.vulkan.pipeline.cache.Cache;
31+
import com.jme3.util.cache.InlineTimedCache;
3132
import com.jme3.vulkan.pipeline.framebuffer.*;
32-
import com.jme3.vulkan.pipeline.graphics.GraphicsPipeline;
33+
import com.jme3.vulkan.pipeline.graphics.DynamicGraphicsPipeline;
34+
import com.jme3.vulkan.pipeline.state.GraphicsState;
3335
import com.jme3.vulkan.render.bucket.GeometryBucket;
36+
import com.jme3.vulkan.render.bucket.RenderElement;
3437
import com.jme3.vulkan.render.bucket.VulkanRenderElement;
3538
import com.jme3.vulkan.surface.Surface;
3639
import com.jme3.vulkan.surface.Swapchain;
@@ -58,10 +61,10 @@ public class SimpleVulkanEngine implements Engine {
5861
private BufferStream stream;
5962
private OutputFrameBuffer outFrameBuffer;
6063

61-
private final Cache<Pipeline> pipelineCache = new Cache<>();
62-
private final Cache<PipelineLayout> pipelineLayoutCache = new Cache<>();
63-
private final Cache<ShaderModule> shaderCache = new Cache<>();
64-
private final Cache<DescriptorSetLayout> descSetLayoutCache = new Cache<>();
64+
private final InlineTimedCache<Pipeline> pipelineCache = new InlineTimedCache<>();
65+
private final InlineTimedCache<PipelineLayout> pipelineLayoutCache = new InlineTimedCache<>();
66+
private final InlineTimedCache<ShaderModule> shaderCache = new InlineTimedCache<>();
67+
private final InlineTimedCache<DescriptorSetLayout> descSetLayoutCache = new InlineTimedCache<>();
6568

6669
private DescriptorSet globalBindings;
6770

@@ -191,16 +194,15 @@ public FrameBuffer<?> getOutputFrameBuffer() {
191194
return outFrameBuffer;
192195
}
193196

194-
private class Frame implements RenderSession {
197+
public class Frame implements RenderSession<SimpleVulkanEngine> {
195198

196199
private final CommandBuffer graphics = graphicsPool.allocate(CommandBuffer.Level.Primary);
197200
private final Semaphore imageAcquired = new BinarySemaphore(device);
198201
private final Semaphore renderComplete = new BinarySemaphore(device);
199202
private final Fence inFlight = new Fence(device, true);
200-
private final StandardRenderSettings settings = new VulkanRenderSettings(graphics);
201203
private boolean outputAvailable = false;
202204

203-
public Frame init() {
205+
protected Frame init() {
204206
inFlight.block(5000L);
205207
outputAvailable = outFrameBuffer.acquireNextTarget(imageAcquired, null, 5000L);
206208
graphics.reset();
@@ -221,7 +223,7 @@ public void close() {
221223
}
222224

223225
@Override
224-
public Engine getEngine() {
226+
public SimpleVulkanEngine getEngine() {
225227
return SimpleVulkanEngine.this;
226228
}
227229

@@ -236,29 +238,33 @@ public void render(Collection<ViewPort> viewPorts, Queue<ShadingTechnique> techn
236238
fbo.beginDynamicRender(graphics,
237239
VulkanImage.Load.DontCare, VulkanImage.Store.Store,
238240
VulkanImage.Load.DontCare, VulkanImage.Store.DontCare);
239-
settings.pushViewPort(vp.getArea());
240-
settings.pushScissor(vp.getArea().toScissor(null));
241+
//settings.pushViewPort(vp.getArea());
242+
//settings.pushScissor(vp.getArea().toScissor(null));
241243
for (GeometryBucket b : vp.gatherGeometry(s -> s.runControlRender(SimpleVulkanEngine.this, vp))) {
242-
b.setupRender(vp, settings);
243-
settings.applySettings();
244+
//b.setupRender(vp, settings);
245+
//settings.applySettings();
244246
for (ShadingTechnique t : techniques) {
245-
t.render(this, vp, b, g -> new EngineRenderElement(vp.getCamera(),
246-
g, graphics, vp.getOutputFrameBuffer(), t.getProgram()));
247+
t.render(this, vp, b);
247248
if (b.isEmpty()) {
248249
break;
249250
}
250251
}
251-
b.cleanupRender(vp, settings);
252+
//b.cleanupRender(vp, settings);
252253
}
253-
settings.popViewPort();
254-
settings.popScissor();
254+
//settings.popViewPort();
255+
//settings.popScissor();
255256
fbo.endDynamicRender(graphics);
256257
}
257258

258259
}
259260

260261
@Override
261-
public void stageShaderSets(int location, SetBind... sets) {
262+
public RenderElement createRenderElement(ViewPort vp, Geometry g, GraphicsState state) {
263+
return new EngineRenderElement(graphics, vp.getOutputFrameBuffer(), vp.getCamera(), g, state);
264+
}
265+
266+
@Override
267+
public void stageShaderSet(int location, SetBindCommand sets) {
262268
graphics.stageShaderSets(location, sets);
263269
}
264270

@@ -293,16 +299,13 @@ private class EngineRenderElement extends VulkanRenderElement {
293299

294300
private final CommandBuffer cmd;
295301
private final FrameBuffer frameBuffer;
302+
private final VertexPipeline pipeline;
296303

297-
public EngineRenderElement(CommandBuffer cmd, ViewPort vp, Geometry geometry) {
298-
super(vp.getCamera(), geometry);
304+
public EngineRenderElement(CommandBuffer cmd, FrameBuffer frameBuffer, Camera cam, Geometry g, GraphicsState state) {
305+
super(cam, g);
299306
this.cmd = cmd;
300-
this.frameBuffer = vp.getOutputFrameBuffer();
301-
}
302-
303-
@Override
304-
protected VertexPipeline createPipeline() {
305-
return GraphicsPipeline.build(device, p -> {
307+
this.frameBuffer = frameBuffer;
308+
this.pipeline = DynamicGraphicsPipeline.build(device, p -> {
306309
p.setCache(pipelineCache);
307310
p.setLayoutCache(pipelineLayoutCache);
308311
p.setShaderCache(shaderCache);
@@ -323,12 +326,17 @@ protected VertexPipeline createPipeline() {
323326

324327
@Override
325328
public void bind() {
326-
cmd.cmdBindPipeline(getPipeline());
329+
cmd.cmdBindPipeline(pipeline);
327330
}
328331

329332
@Override
330333
public void render() {
331-
getMesh().render(cmd, getPipeline());
334+
getMesh().render(cmd, pipeline);
335+
}
336+
337+
@Override
338+
public long getPipelineSortPosition() {
339+
return 0;
332340
}
333341

334342
}

jme3-core/src/main/java/com/jme3/material/Material.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,25 @@
3131
*/
3232
package com.jme3.material;
3333

34-
import com.jme3.vulkan.material.experimental.ShaderInterface;
35-
36-
import java.util.function.Function;
34+
import com.jme3.vulkan.material.experimental.ShadingInterface;
35+
import com.jme3.vulkan.pipeline.state.GraphicsState;
3736

3837
/**
3938
*
4039
* @author codex
4140
*/
4241
public interface Material {
4342

44-
void setParameter(String name, Object value);
45-
46-
<P> P getParameter(String name);
43+
<T extends ShadingInterface> void setInterface(Class<T> type, T shaderInterface);
4744

48-
<T extends ShaderInterface> void setInterface(Class<T> type, Function<Material, T> factory);
45+
<T extends ShadingInterface> T getInterface(Class<T> type);
4946

50-
<T extends ShaderInterface> T getInterface(Class<T> type);
47+
boolean containsInterface(Class<? extends ShadingInterface> type);
5148

52-
boolean containsInterface(Class<? extends ShaderInterface> type);
49+
GraphicsState getGraphicsState();
5350

54-
RenderState getAdditionalRenderState();
51+
default <T extends ShadingInterface> void setInterface(T shaderInterface) {
52+
setInterface((Class<T>)shaderInterface.getClass(), shaderInterface);
53+
}
5554

5655
}

jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ private void renderProcessing(Renderer r, FrameBuffer buff, Material mat) {
212212
// viewPort.getCamera().resize(originalWidth, originalHeight, false);
213213
// viewPort.getCamera().setViewPort(left, right, bottom, top);
214214
// renderManager.setCamera(viewPort.getCamera(), false);
215-
commands.setViewPort(viewPort.getArea());
215+
commands.cmdSetViewPort(viewPort.getArea());
216216
if (mat.getAdditionalRenderState().isDepthWrite()) {
217217
mat.getAdditionalRenderState().setDepthTest(false);
218218
mat.getAdditionalRenderState().setDepthWrite(false);
@@ -221,7 +221,7 @@ private void renderProcessing(Renderer r, FrameBuffer buff, Material mat) {
221221
// viewPort.getCamera().resize(buff.getWidth(), buff.getHeight(), false);
222222
// viewPort.getCamera().setViewPort(0, 1, 0, 1);
223223
// renderManager.setCamera(viewPort.getCamera(), false);
224-
commands.setViewPort(new ViewPortArea(buff.getWidth(), buff.getHeight()));
224+
commands.cmdSetViewPort(new ViewPortArea(buff.getWidth(), buff.getHeight()));
225225
// why are we depth testing at all?
226226
// mat.getAdditionalRenderState().setDepthTest(true);
227227
// mat.getAdditionalRenderState().setDepthWrite(true);
@@ -235,7 +235,7 @@ private void renderProcessing(Renderer r, FrameBuffer buff, Material mat) {
235235

236236
// r.setFrameBuffer(buff);
237237
// r.clearBuffers(true, true, true);
238-
commands.bindFrameBuffer(buff);
238+
commands.cmdBindFrameBuffer(buff);
239239
//renderManager.renderGeometry(fsQuad);
240240
commands.renderGeometry(fsQuad);
241241
}
@@ -346,7 +346,7 @@ public void postFrame(FrameBuffer out) {
346346
}
347347
renderFilterChain(renderer, sceneBuffer);
348348
//renderer.setFrameBuffer(outputBuffer);
349-
commands.bindFrameBuffer(outputBuffer);
349+
commands.cmdBindFrameBuffer(outputBuffer);
350350

351351
//viewport can be null if no filters are enabled
352352
if (viewPort != null) {
@@ -374,7 +374,7 @@ public void preFrame(float tpf) {
374374
// viewPort.getCamera().setViewPort(0, 1, 0, 1);
375375
// viewPort.getCamera().update();
376376
// renderManager.setCamera(viewPort.getCamera(), false);
377-
commands.setViewPort(new ViewPortArea(width, height));
377+
commands.cmdSetViewPort(new ViewPortArea(width, height));
378378
}
379379
}
380380

@@ -432,7 +432,7 @@ public void cleanup() {
432432
// viewPort.getCamera().resize(originalWidth, originalHeight, true);
433433
// viewPort.getCamera().setViewPort(left, right, bottom, top);
434434
viewPort.setOutputFrameBuffer(outputBuffer);
435-
commands.setViewPort(viewPort.getArea());
435+
commands.cmdSetViewPort(viewPort.getArea());
436436
viewPort = null;
437437

438438
// if(renderFrameBuffer != null){

jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565

6666
import com.jme3.util.struct.Struct;
6767
import com.jme3.vulkan.OpenGLEnums;
68-
import com.jme3.vulkan.buffers.BufferMapping;
68+
import com.jme3.vulkan.buffers.mapping.BufferMapping;
6969
import com.jme3.vulkan.buffers.GlBuffer;
7070
import com.jme3.vulkan.buffers.IdxBuffer;
7171
import com.jme3.vulkan.buffers.stream.DirtyRegions;

jme3-core/src/main/java/com/jme3/renderer/queue/OpaqueComparator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class OpaqueComparator implements Comparator<RenderElement> {
3939

4040
@Override
4141
public int compare(RenderElement o1, RenderElement o2) {
42-
int result = Long.compare(o1.getTechniqueSortPosition(), o1.getTechniqueSortPosition());
42+
int result = Long.compare(o1.getPipelineSortPosition(), o1.getPipelineSortPosition());
4343
if (result == 0) {
4444
result = Long.compare(o1.getMaterialSortPosition(), o2.getMaterialSortPosition());
4545
if (result == 0) {

0 commit comments

Comments
 (0)