Progress on UI Renderer, getting to a good level :)
This commit is contained in:
+4
@@ -1,6 +1,7 @@
|
|||||||
package speiger.src.coreengine.platform.graphics.api.core;
|
package speiger.src.coreengine.platform.graphics.api.core;
|
||||||
|
|
||||||
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
||||||
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
|
import speiger.src.coreengine.platform.graphics.api.texture.Texture;
|
||||||
@@ -13,7 +14,10 @@ public interface GraphicsCommandBuffer extends GraphicsResource, CommandBuffer {
|
|||||||
GraphicsCommandBuffer setScissors(int x, int y, int width, int height);
|
GraphicsCommandBuffer setScissors(int x, int y, int width, int height);
|
||||||
|
|
||||||
GraphicsCommandBuffer pipeline(ShaderPipeline pipeline);
|
GraphicsCommandBuffer pipeline(ShaderPipeline pipeline);
|
||||||
|
|
||||||
GraphicsCommandBuffer mesh(Mesh mesh);
|
GraphicsCommandBuffer mesh(Mesh mesh);
|
||||||
|
GraphicsCommandBuffer mesh(DynamicMesh mesh);
|
||||||
|
|
||||||
GraphicsCommandBuffer texture(int binding, SampledTexture texture);
|
GraphicsCommandBuffer texture(int binding, SampledTexture texture);
|
||||||
GraphicsCommandBuffer texture(int binding, Texture texture, AccessType access);
|
GraphicsCommandBuffer texture(int binding, Texture texture, AccessType access);
|
||||||
|
|
||||||
|
|||||||
+2
@@ -6,6 +6,7 @@ import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
|||||||
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
|
||||||
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
|
import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.sampler.Sampler;
|
import speiger.src.coreengine.platform.graphics.api.sampler.Sampler;
|
||||||
import speiger.src.coreengine.platform.graphics.api.sampler.SamplerSettings;
|
import speiger.src.coreengine.platform.graphics.api.sampler.SamplerSettings;
|
||||||
@@ -28,6 +29,7 @@ public interface GraphicsDevice {
|
|||||||
Texture createTexture(TextureSettings data, int width, int height);
|
Texture createTexture(TextureSettings data, int width, int height);
|
||||||
Sampler createSampler(SamplerSettings settings);
|
Sampler createSampler(SamplerSettings settings);
|
||||||
Mesh createMesh(Mesh.Builder builder);
|
Mesh createMesh(Mesh.Builder builder);
|
||||||
|
DynamicMesh createDynamicMesh(DynamicMesh.Builder builder);
|
||||||
TimeQueryPool createQueryPool(int size);
|
TimeQueryPool createQueryPool(int size);
|
||||||
void preloadPipelines(List<ShaderPipeline> graphics, List<ComputePipeline> compute);
|
void preloadPipelines(List<ShaderPipeline> graphics, List<ComputePipeline> compute);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package speiger.src.coreengine.platform.graphics.api.mesh;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import speiger.src.collections.ints.collections.IntIterable;
|
||||||
|
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
|
||||||
|
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.IndeciesType;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;
|
||||||
|
|
||||||
|
public abstract class DynamicMesh implements GraphicsResource {
|
||||||
|
protected Int2ObjectMap<VertexBuffer> buffers;
|
||||||
|
@Nullable
|
||||||
|
protected VertexBuffer indeciesBuffer;
|
||||||
|
@Nullable
|
||||||
|
protected IndeciesType indeciesType;
|
||||||
|
|
||||||
|
public DynamicMesh(Int2ObjectMap<VertexBuffer> buffers, @Nullable VertexBuffer indeciesBuffer, @Nullable IndeciesType type) {
|
||||||
|
this.buffers = buffers;
|
||||||
|
this.indeciesBuffer = indeciesBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void closeWithBuffers();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public VertexBuffer indeciesBuffer() {
|
||||||
|
return indeciesBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public IndeciesType indeciesType() {
|
||||||
|
return indeciesType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexBuffer buffer(int binding) {
|
||||||
|
return buffers.get(binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicMesh indexBuffer(@Nullable VertexBuffer indexBuffer, @Nullable IndeciesType indeciesType) {
|
||||||
|
this.indeciesBuffer = indexBuffer;
|
||||||
|
this.indeciesType = indeciesType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicMesh buffer(int binding, @Nullable VertexBuffer buffer) {
|
||||||
|
buffers.put(binding, buffer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntIterable bindings() {
|
||||||
|
return buffers.keySet().unmodifiable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
Int2ObjectMap<BufferState> allocateState = new Int2ObjectOpenHashMap<>();
|
||||||
|
IndeciesType type = IndeciesType.INT;
|
||||||
|
OptionalInt preallocated = OptionalInt.empty();
|
||||||
|
boolean autoGenerate;
|
||||||
|
|
||||||
|
private Builder() {}
|
||||||
|
|
||||||
|
public Builder autogenerate() {
|
||||||
|
autoGenerate = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder preallocate(int bytes) {
|
||||||
|
preallocated = OptionalInt.of(bytes);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder indecies(IndeciesType type) {
|
||||||
|
type = Objects.requireNonNull(type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder bufferState(int index, BufferState state) {
|
||||||
|
allocateState.put(index, state);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAutogenerated() {
|
||||||
|
return autoGenerate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndeciesType indecies() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionalInt preAllocated() {
|
||||||
|
return preallocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int2ObjectMap<BufferState> buffers() {
|
||||||
|
return allocateState.unmodifiable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferState getIndeciesBuffer() {
|
||||||
|
return allocateState.getOrDefault(-1, BufferState.STATIC_DRAW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,25 +16,30 @@ import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
|
|||||||
public abstract class Mesh implements GraphicsResource {
|
public abstract class Mesh implements GraphicsResource {
|
||||||
protected final Int2ObjectMap<LayoutInfo> layouts;
|
protected final Int2ObjectMap<LayoutInfo> layouts;
|
||||||
protected Int2ObjectMap<VertexBuffer> buffers;
|
protected Int2ObjectMap<VertexBuffer> buffers;
|
||||||
|
@Nullable
|
||||||
protected VertexBuffer indeciesBuffer;
|
protected VertexBuffer indeciesBuffer;
|
||||||
|
@Nullable
|
||||||
protected IndeciesType indeciesType;
|
protected IndeciesType indeciesType;
|
||||||
|
|
||||||
public Mesh(Int2ObjectMap<LayoutInfo> layouts, Int2ObjectMap<VertexBuffer> buffers, @Nullable VertexBuffer indeciesBuffer, @Nullable IndeciesType type) {
|
public Mesh(Int2ObjectMap<LayoutInfo> layouts, Int2ObjectMap<VertexBuffer> buffers, @Nullable VertexBuffer indeciesBuffer, @Nullable IndeciesType type) {
|
||||||
this.layouts = layouts;
|
this.layouts = layouts;
|
||||||
this.buffers = buffers;
|
this.buffers = buffers;
|
||||||
this.indeciesBuffer = indeciesBuffer;
|
this.indeciesBuffer = indeciesBuffer;
|
||||||
|
this.indeciesType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void closeWithBuffers();
|
public abstract void closeWithBuffers();
|
||||||
|
|
||||||
public Int2ObjectMap<LayoutInfo> layouts() {
|
public Int2ObjectMap<LayoutInfo> layouts() {
|
||||||
return layouts;
|
return layouts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public VertexBuffer indeciesBuffer() {
|
public VertexBuffer indeciesBuffer() {
|
||||||
return indeciesBuffer;
|
return indeciesBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public IndeciesType indeciesType() {
|
public IndeciesType indeciesType() {
|
||||||
return indeciesType;
|
return indeciesType;
|
||||||
}
|
}
|
||||||
@@ -43,13 +48,13 @@ public abstract class Mesh implements GraphicsResource {
|
|||||||
return buffers.get(binding);
|
return buffers.get(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mesh indexBuffer(VertexBuffer indexBuffer, IndeciesType indeciesType) {
|
public Mesh indexBuffer(@Nullable VertexBuffer indexBuffer, @Nullable IndeciesType indeciesType) {
|
||||||
this.indeciesBuffer = indexBuffer;
|
this.indeciesBuffer = indexBuffer;
|
||||||
this.indeciesType = indeciesType;
|
this.indeciesType = indeciesType;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mesh buffer(int binding, VertexBuffer buffer) {
|
public Mesh buffer(int binding, @Nullable VertexBuffer buffer) {
|
||||||
buffers.put(binding, buffer);
|
buffers.put(binding, buffer);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -59,7 +64,7 @@ public abstract class Mesh implements GraphicsResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
Int2ObjectMap<BufferState> allocateState = new Int2ObjectOpenHashMap<BufferState>().setDefaultReturnValue(BufferState.STATIC_READ);
|
Int2ObjectMap<BufferState> allocateState = new Int2ObjectOpenHashMap<BufferState>().setDefaultReturnValue(BufferState.STATIC_DRAW);
|
||||||
Int2ObjectMap<LayoutInfo> layouts = Int2ObjectMap.builder().linkedMap();
|
Int2ObjectMap<LayoutInfo> layouts = Int2ObjectMap.builder().linkedMap();
|
||||||
IndeciesType type = IndeciesType.INT;
|
IndeciesType type = IndeciesType.INT;
|
||||||
OptionalInt preallocated = OptionalInt.empty();
|
OptionalInt preallocated = OptionalInt.empty();
|
||||||
|
|||||||
+3
-1
@@ -46,5 +46,7 @@ public interface IVertexBuffer extends IVertexBuilder {
|
|||||||
throw new IllegalStateException("Expected State [Usage="+current.usage()+", Size="+current.size()+", Type="+current.type()+"], wasn't present. Actual State [Usage="+usage+", Size="+size+", Type="+type+"]");
|
throw new IllegalStateException("Expected State [Usage="+current.usage()+", Size="+current.size()+", Type="+current.type()+"], wasn't present. Actual State [Usage="+usage+", Size="+size+", Type="+type+"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public record BufferResult(DrawMode mode, int startVertex, int endVertex) {}
|
public record BufferResult(DrawMode mode, int startVertex, int endVertex) {
|
||||||
|
public int vertexCount() { return endVertex - startVertex; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-2
@@ -1,14 +1,17 @@
|
|||||||
package speiger.src.coreengine.platform.graphics.api.vertex.builder;
|
package speiger.src.coreengine.platform.graphics.api.vertex.builder;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import speiger.src.coreengine.math.MathUtils;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
|
import speiger.src.coreengine.platform.graphics.api.shader.states.DrawMode;
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
|
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
|
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
|
||||||
|
|
||||||
public class VertexBuilder implements IVertexBuffer, AutoCloseable {
|
public class VertexBuilder implements IVertexBuffer, AutoCloseable {
|
||||||
|
boolean autoAlign;
|
||||||
boolean noFree = false;
|
boolean noFree = false;
|
||||||
DrawMode mode;
|
DrawMode mode;
|
||||||
ByteBuffer buffer;
|
ByteBuffer buffer;
|
||||||
@@ -29,6 +32,11 @@ public class VertexBuilder implements IVertexBuffer, AutoCloseable {
|
|||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VertexBuilder withAutoAlign() {
|
||||||
|
this.autoAlign = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public VertexBuilder withoutFree() {
|
public VertexBuilder withoutFree() {
|
||||||
noFree = true;
|
noFree = true;
|
||||||
return this;
|
return this;
|
||||||
@@ -36,8 +44,12 @@ public class VertexBuilder implements IVertexBuffer, AutoCloseable {
|
|||||||
|
|
||||||
public VertexBuilder start(DrawMode mode, VertexLayout layout) {
|
public VertexBuilder start(DrawMode mode, VertexLayout layout) {
|
||||||
if(index != 0) throw new IllegalStateException("Can't change Layout mid Writing");
|
if(index != 0) throw new IllegalStateException("Can't change Layout mid Writing");
|
||||||
this.mode = mode;
|
if(autoAlign && this.layout != layout) {
|
||||||
this.layout = layout;
|
totalStoredBytes = MathUtils.roundAlign(totalStoredBytes, layout.bytes());
|
||||||
|
ensureCapacity(totalStoredBytes + (layout.bytes() * mode.primitiveLength()));
|
||||||
|
}
|
||||||
|
this.mode = Objects.requireNonNull(mode);
|
||||||
|
this.layout = Objects.requireNonNull(layout);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +67,8 @@ public class VertexBuilder implements IVertexBuffer, AutoCloseable {
|
|||||||
public boolean is(DrawMode mode, VertexLayout layout) { return this.mode == mode && this.layout == layout; }
|
public boolean is(DrawMode mode, VertexLayout layout) { return this.mode == mode && this.layout == layout; }
|
||||||
public DrawMode mode() { return mode; }
|
public DrawMode mode() { return mode; }
|
||||||
public VertexLayout getFormat() { return layout; }
|
public VertexLayout getFormat() { return layout; }
|
||||||
|
public long memoryPointer() { return MemoryUtil.memAddress(buffer); }
|
||||||
|
public int totalStoredBytes() { return totalStoredBytes; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
@@ -70,6 +84,12 @@ public class VertexBuilder implements IVertexBuffer, AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferResult finish() {
|
public BufferResult finish() {
|
||||||
|
if(autoAlign) {
|
||||||
|
int count = vertecies - lastVertecies;
|
||||||
|
lastVertecies = vertecies;
|
||||||
|
int vertecies = totalStoredBytes / layout.bytes();
|
||||||
|
return new BufferResult(mode, vertecies - count, vertecies);
|
||||||
|
}
|
||||||
BufferResult result = new BufferResult(mode, lastVertecies, vertecies);
|
BufferResult result = new BufferResult(mode, lastVertecies, vertecies);
|
||||||
lastVertecies = vertecies;
|
lastVertecies = vertecies;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+21
-1
@@ -45,23 +45,26 @@ import speiger.src.coreengine.platform.graphics.api.compute.ComputePipeline;
|
|||||||
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
||||||
import speiger.src.coreengine.platform.graphics.api.core.GraphicsDevice;
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsDevice;
|
||||||
import speiger.src.coreengine.platform.graphics.api.core.TimeQueryPool;
|
import speiger.src.coreengine.platform.graphics.api.core.TimeQueryPool;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh.LayoutInfo;
|
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh.LayoutInfo;
|
||||||
import speiger.src.coreengine.platform.graphics.api.sampler.SamplerSettings;
|
import speiger.src.coreengine.platform.graphics.api.sampler.SamplerSettings;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.VertexBinding;
|
import speiger.src.coreengine.platform.graphics.api.shader.VertexBinding;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.states.ShaderType;
|
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferBinding;
|
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferBinding;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferMode;
|
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferMode;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureBinding;
|
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureBinding;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureMode;
|
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureMode;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.shader.states.ShaderType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.texture.TextureSettings;
|
import speiger.src.coreengine.platform.graphics.api.texture.TextureSettings;
|
||||||
import speiger.src.coreengine.platform.graphics.api.texture.states.SwizzleMask;
|
import speiger.src.coreengine.platform.graphics.api.texture.states.SwizzleMask;
|
||||||
import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
|
import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.utils.ExecutionType;
|
import speiger.src.coreengine.platform.graphics.api.utils.ExecutionType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
|
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLDynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.VertexArrayCache;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
|
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderCache;
|
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderCache;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
|
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
|
||||||
@@ -78,6 +81,7 @@ public class GLGraphicsDevice implements GraphicsDevice {
|
|||||||
static final Map<ID, String> IMPORTS = Object2ObjectMap.builder().<ID, String>map().synchronize();
|
static final Map<ID, String> IMPORTS = Object2ObjectMap.builder().<ID, String>map().synchronize();
|
||||||
Object2IntMap<ID> shaderCache = new Object2IntOpenHashMap<>();
|
Object2IntMap<ID> shaderCache = new Object2IntOpenHashMap<>();
|
||||||
Object2ObjectMap<ID, ShaderInstance> programCache = new Object2ObjectOpenHashMap<>();
|
Object2ObjectMap<ID, ShaderInstance> programCache = new Object2ObjectOpenHashMap<>();
|
||||||
|
VertexArrayCache vertexCache = new VertexArrayCache();
|
||||||
AssetManager manager;
|
AssetManager manager;
|
||||||
GLCapabilities capabilities;
|
GLCapabilities capabilities;
|
||||||
GLStates states = new GLStates();
|
GLStates states = new GLStates();
|
||||||
@@ -167,6 +171,22 @@ public class GLGraphicsDevice implements GraphicsDevice {
|
|||||||
return new GLMesh(builder.info(), new Int2ObjectOpenHashMap<>(), null, null, false);
|
return new GLMesh(builder.info(), new Int2ObjectOpenHashMap<>(), null, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicMesh createDynamicMesh(DynamicMesh.Builder builder) {
|
||||||
|
if(builder.isAutogenerated()) {
|
||||||
|
OptionalInt preAllocation = builder.preAllocated();
|
||||||
|
Int2ObjectMap<VertexBuffer> buffers = new Int2ObjectLinkedOpenHashMap<>();
|
||||||
|
for(Int2ObjectMap.Entry<BufferState> entry : builder.buffers().int2ObjectEntrySet()) {
|
||||||
|
int key = entry.getIntKey();
|
||||||
|
if(key == -1) continue;
|
||||||
|
buffers.put(key, preAllocation.isPresent() ? createBuffer(BufferType.ARRAY_BUFFER, entry.getValue(), preAllocation.getAsInt()) : createBuffer(BufferType.ARRAY_BUFFER, entry.getValue()));
|
||||||
|
}
|
||||||
|
return new GLDynamicMesh(buffers, createBuffer(BufferType.ELEMENT_BUFFER, builder.getIndeciesBuffer()), builder.indecies(), true);
|
||||||
|
|
||||||
|
}
|
||||||
|
return new GLDynamicMesh(new Int2ObjectOpenHashMap<>(), null, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TimeQueryPool createQueryPool(int size) {
|
public TimeQueryPool createQueryPool(int size) {
|
||||||
return new GLTimeQueryPool(size);
|
return new GLTimeQueryPool(size);
|
||||||
|
|||||||
+21
@@ -11,6 +11,7 @@ import org.lwjgl.opengl.GL45;
|
|||||||
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
||||||
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.ColorTarget;
|
import speiger.src.coreengine.platform.graphics.api.shader.ColorTarget;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.DepthTarget;
|
import speiger.src.coreengine.platform.graphics.api.shader.DepthTarget;
|
||||||
@@ -21,6 +22,7 @@ import speiger.src.coreengine.platform.graphics.api.utils.AccessType;
|
|||||||
import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
|
import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
|
||||||
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
|
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLDynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
|
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
|
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
|
||||||
@@ -39,6 +41,7 @@ public class GLImmidateCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
ShaderPipeline pipeline;
|
ShaderPipeline pipeline;
|
||||||
ShaderInstance shader;
|
ShaderInstance shader;
|
||||||
GLMesh mesh;
|
GLMesh mesh;
|
||||||
|
GLDynamicMesh dynamicMesh;
|
||||||
|
|
||||||
public GLImmidateCommandBuffer(GLGraphicsDevice device) {
|
public GLImmidateCommandBuffer(GLGraphicsDevice device) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
@@ -102,6 +105,7 @@ public class GLImmidateCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
ColorTarget color = pipeline.colorTarget();
|
ColorTarget color = pipeline.colorTarget();
|
||||||
color.blend().ifPresentOrElse(states.blend::enableSet, states.blend::disable);
|
color.blend().ifPresentOrElse(states.blend::enableSet, states.blend::disable);
|
||||||
states.setColorMask(color.writeMask());
|
states.setColorMask(color.writeMask());
|
||||||
|
if(dynamicMesh != null) bindDynamicMesh();
|
||||||
recorded++;
|
recorded++;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -113,10 +117,27 @@ public class GLImmidateCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
if(this.mesh == mesh) return this;
|
if(this.mesh == mesh) return this;
|
||||||
this.mesh = (GLMesh)mesh;
|
this.mesh = (GLMesh)mesh;
|
||||||
GL30.glBindVertexArray(this.mesh.id());
|
GL30.glBindVertexArray(this.mesh.id());
|
||||||
|
this.dynamicMesh = null;
|
||||||
recorded++;
|
recorded++;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GraphicsCommandBuffer mesh(DynamicMesh mesh) {
|
||||||
|
Objects.requireNonNull(mesh);
|
||||||
|
ensureDrawing();
|
||||||
|
if(this.dynamicMesh == mesh) return this;
|
||||||
|
this.dynamicMesh = (GLDynamicMesh)mesh;
|
||||||
|
bindDynamicMesh();
|
||||||
|
this.mesh = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void bindDynamicMesh() {
|
||||||
|
if(pipeline == null || dynamicMesh == null) return;
|
||||||
|
device.vertexCache.apply(pipeline, dynamicMesh);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GraphicsCommandBuffer texture(int binding, SampledTexture texture) {
|
public GraphicsCommandBuffer texture(int binding, SampledTexture texture) {
|
||||||
Objects.requireNonNull(texture);
|
Objects.requireNonNull(texture);
|
||||||
|
|||||||
+24
-3
@@ -15,6 +15,7 @@ import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
|||||||
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.buffer.states.IndeciesType;
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.IndeciesType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
import speiger.src.coreengine.platform.graphics.api.mesh.Mesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.ColorTarget;
|
import speiger.src.coreengine.platform.graphics.api.shader.ColorTarget;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.DepthTarget;
|
import speiger.src.coreengine.platform.graphics.api.shader.DepthTarget;
|
||||||
@@ -27,7 +28,9 @@ import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
|
|||||||
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
|
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
|
||||||
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager.NoOp;
|
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager.NoOp;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLDynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.GLMesh;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.mesh.VertexArrayCache;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
|
import speiger.src.coreengine.platform.graphics.opengl.sampler.GLSampler;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
|
import speiger.src.coreengine.platform.graphics.opengl.shader.ShaderInstance;
|
||||||
import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
|
import speiger.src.coreengine.platform.graphics.opengl.texture.GLTexture;
|
||||||
@@ -44,7 +47,7 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
ShaderPipeline pipeline;
|
ShaderPipeline pipeline;
|
||||||
ShaderInstance shader;
|
ShaderInstance shader;
|
||||||
GLMesh mesh;
|
GLMesh mesh;
|
||||||
|
GLDynamicMesh dynamicMesh;
|
||||||
|
|
||||||
public GLRecordingCommandBuffer(GLGraphicsDevice device) {
|
public GLRecordingCommandBuffer(GLGraphicsDevice device) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
@@ -95,7 +98,7 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
//TODO implement logging
|
//TODO implement logging
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
tasks.add(new SetPipeline(pipeline, shader, device.states));
|
tasks.add(new SetPipeline(pipeline, shader, dynamicMesh, device.states, device.vertexCache));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +109,18 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
if(this.mesh == mesh) return this;
|
if(this.mesh == mesh) return this;
|
||||||
this.mesh = (GLMesh)mesh;
|
this.mesh = (GLMesh)mesh;
|
||||||
this.tasks.add(new SetMesh(this.mesh));
|
this.tasks.add(new SetMesh(this.mesh));
|
||||||
|
this.dynamicMesh = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GraphicsCommandBuffer mesh(DynamicMesh mesh) {
|
||||||
|
Objects.requireNonNull(mesh);
|
||||||
|
ensureDrawing();
|
||||||
|
if(this.dynamicMesh == mesh) return this;
|
||||||
|
this.dynamicMesh = (GLDynamicMesh)mesh;
|
||||||
|
this.tasks.add(new SetDynamicMesh(dynamicMesh, pipeline, device.vertexCache));
|
||||||
|
this.mesh = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +253,7 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
public void run() { states.scissors.set(area); }
|
public void run() { states.scissors.set(area); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public record SetPipeline(ShaderPipeline pipeline, ShaderInstance instance, GLStates states) implements Runnable {
|
public record SetPipeline(ShaderPipeline pipeline, ShaderInstance instance, GLDynamicMesh mesh, GLStates states, VertexArrayCache cache) implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
states.shaders.bind(instance);
|
states.shaders.bind(instance);
|
||||||
@@ -255,6 +270,7 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
ColorTarget color = pipeline.colorTarget();
|
ColorTarget color = pipeline.colorTarget();
|
||||||
color.blend().ifPresentOrElse(states.blend::enableSet, states.blend::disable);
|
color.blend().ifPresentOrElse(states.blend::enableSet, states.blend::disable);
|
||||||
states.setColorMask(color.writeMask());
|
states.setColorMask(color.writeMask());
|
||||||
|
if(mesh != null) cache.apply(pipeline, mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +279,11 @@ public class GLRecordingCommandBuffer implements GraphicsCommandBuffer {
|
|||||||
public void run() { GL30.glBindVertexArray(mesh.id()); }
|
public void run() { GL30.glBindVertexArray(mesh.id()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record SetDynamicMesh(GLDynamicMesh mesh, ShaderPipeline pipeline, VertexArrayCache cache) implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() { cache.apply(pipeline, mesh); }
|
||||||
|
}
|
||||||
|
|
||||||
public record SetTexture(int binding, GLTexture texture, GLSampler sampler, GLStates states) implements Runnable {
|
public record SetTexture(int binding, GLTexture texture, GLSampler sampler, GLStates states) implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package speiger.src.coreengine.platform.graphics.opengl.mesh;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.buffer.VertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.IndeciesType;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
|
|
||||||
|
public class GLDynamicMesh extends DynamicMesh {
|
||||||
|
boolean managed;
|
||||||
|
boolean invalid = false;
|
||||||
|
|
||||||
|
public GLDynamicMesh(Int2ObjectMap<VertexBuffer> buffers, @Nullable VertexBuffer indeciesBuffer, @Nullable IndeciesType type, boolean managed) {
|
||||||
|
super(buffers, indeciesBuffer, type);
|
||||||
|
this.managed = managed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRemoved() { return invalid; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
if(invalid) return;
|
||||||
|
invalid = true;
|
||||||
|
if(!managed) return;
|
||||||
|
if(indeciesBuffer != null) indeciesBuffer.remove();
|
||||||
|
buffers.values().forEach(VertexBuffer::close);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeWithBuffers() {
|
||||||
|
boolean wasManaged = managed;
|
||||||
|
managed = true;
|
||||||
|
close();
|
||||||
|
managed = wasManaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -86,7 +86,7 @@ public class GLMesh extends Mesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void closeWithBuffers() {
|
public void closeWithBuffers() {
|
||||||
boolean wasManaged = managed;
|
boolean wasManaged = managed;
|
||||||
managed = true;
|
managed = true;
|
||||||
close();
|
close();
|
||||||
|
|||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
package speiger.src.coreengine.platform.graphics.opengl.mesh;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
import org.lwjgl.opengl.GL45;
|
||||||
|
|
||||||
|
import speiger.src.collections.ints.maps.impl.hash.Int2IntOpenHashMap;
|
||||||
|
import speiger.src.collections.ints.maps.interfaces.Int2IntMap;
|
||||||
|
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.shader.VertexBinding;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.vertex.VertexLayout.Element;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.buffer.GLVertexBuffer;
|
||||||
|
import speiger.src.coreengine.platform.graphics.opengl.utils.GLUtils;
|
||||||
|
|
||||||
|
public class VertexArrayCache {
|
||||||
|
Map<ShaderPipeline, CacheEntry> cache = new Object2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
public void apply(ShaderPipeline pipeline, GLDynamicMesh mesh) {
|
||||||
|
CacheEntry entry = cache.get(pipeline);
|
||||||
|
if(entry == null) {
|
||||||
|
entry = new CacheEntry(GL45.glCreateVertexArrays(), toIds(mesh));
|
||||||
|
cache.put(pipeline, entry);
|
||||||
|
apply(entry.vao, pipeline, mesh);
|
||||||
|
GL30.glBindVertexArray(entry.vao);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Int2IntMap newIds = toIds(mesh);
|
||||||
|
if(entry.existing.equals(newIds)) {
|
||||||
|
GL30.glBindVertexArray(entry.vao);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry.existing = newIds;
|
||||||
|
apply(entry.vao, pipeline, mesh);
|
||||||
|
GL30.glBindVertexArray(entry.vao);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply(int vao, ShaderPipeline pipeline, DynamicMesh mesh) {
|
||||||
|
for(VertexBinding binding : pipeline.attributes()) {
|
||||||
|
bindBuffer(vao, binding.bindingIndex(), binding, mesh);
|
||||||
|
}
|
||||||
|
if(mesh.indeciesBuffer() != null) {
|
||||||
|
mesh.indeciesBuffer().bind();
|
||||||
|
GL45.glVertexArrayElementBuffer(vao, ((GLVertexBuffer)mesh.indeciesBuffer()).id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindBuffer(int vao, int binding, VertexBinding info, DynamicMesh mesh) {
|
||||||
|
VertexLayout layout = info.layout();
|
||||||
|
GLVertexBuffer buffer = (GLVertexBuffer)mesh.buffer(binding);
|
||||||
|
buffer.bind();
|
||||||
|
GL45.glVertexArrayVertexBuffer(vao, binding, buffer.id(), 0, layout.bytes());
|
||||||
|
if(info.instanceOffset() > 0) GL45.glVertexArrayBindingDivisor(vao, binding, info.instanceOffset());
|
||||||
|
int index = 0;
|
||||||
|
for(Element element : layout) {
|
||||||
|
GL45.glVertexArrayAttribFormat(vao, element.index(), element.size(), GLUtils.toGL(element.type()), element.normalized(), layout.offset(index++));
|
||||||
|
GL45.glVertexArrayAttribBinding(vao, element.index(), binding);
|
||||||
|
GL45.glEnableVertexArrayAttrib(vao, element.index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Int2IntMap toIds(GLDynamicMesh mesh) {
|
||||||
|
Int2IntMap existing = new Int2IntOpenHashMap();
|
||||||
|
for(int entry : mesh.bindings()) {
|
||||||
|
existing.put(entry, ((GLVertexBuffer)mesh.buffer(entry)).id());
|
||||||
|
}
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CacheEntry {
|
||||||
|
Int2IntMap existing;
|
||||||
|
int vao;
|
||||||
|
public CacheEntry(int vao, Int2IntMap existing) {
|
||||||
|
this.existing = existing;
|
||||||
|
this.vao = vao;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
package speiger.src.coreengine.ui.gui.renderer;
|
package speiger.src.coreengine.ui.gui.renderer;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import speiger.src.coreengine.math.vector.matrix.Matrix4f;
|
import speiger.src.coreengine.math.vector.matrix.Matrix4f;
|
||||||
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.builder.IVertexBuilder;
|
import speiger.src.coreengine.platform.graphics.api.vertex.builder.IVertexBuilder;
|
||||||
|
|
||||||
public interface UIDrawer {
|
public interface UIDrawer {
|
||||||
ShaderPipeline pipeline();
|
ShaderPipeline pipeline();
|
||||||
|
@Nullable
|
||||||
|
SampledTexture texture();
|
||||||
void buildVertecies(IVertexBuilder builder, Matrix4f matrix);
|
void buildVertecies(IVertexBuilder builder, Matrix4f matrix);
|
||||||
|
boolean requiresSpecialArgs();
|
||||||
void setupExtra(GraphicsCommandBuffer buffer);
|
void setupExtra(GraphicsCommandBuffer buffer);
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,27 @@
|
|||||||
package speiger.src.coreengine.ui.gui.renderer;
|
package speiger.src.coreengine.ui.gui.renderer;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import speiger.src.collections.ints.collections.IntStack;
|
import speiger.src.collections.ints.collections.IntStack;
|
||||||
import speiger.src.collections.ints.lists.IntArrayList;
|
import speiger.src.collections.ints.lists.IntArrayList;
|
||||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||||
import speiger.src.collections.utils.Stack;
|
import speiger.src.collections.utils.Stack;
|
||||||
import speiger.src.coreengine.math.MathUtils;
|
|
||||||
import speiger.src.coreengine.math.bits.BitUtil;
|
import speiger.src.coreengine.math.bits.BitUtil;
|
||||||
|
import speiger.src.coreengine.math.vector.ints.Vec4i;
|
||||||
import speiger.src.coreengine.math.vector.matrix.Matrix4fStack;
|
import speiger.src.coreengine.math.vector.matrix.Matrix4fStack;
|
||||||
import speiger.src.coreengine.math.vector.quaternion.Quaternion;
|
import speiger.src.coreengine.math.vector.quaternion.Quaternion;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsCommandBuffer;
|
||||||
import speiger.src.coreengine.platform.graphics.api.core.GraphicsDevice;
|
import speiger.src.coreengine.platform.graphics.api.core.GraphicsDevice;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.mesh.DynamicMesh;
|
||||||
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
import speiger.src.coreengine.platform.graphics.api.shader.ShaderPipeline;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.utils.BufferOwner;
|
||||||
|
import speiger.src.coreengine.platform.graphics.api.utils.ExecutionType;
|
||||||
import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
|
import speiger.src.coreengine.platform.graphics.api.utils.SampledTexture;
|
||||||
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
|
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager;
|
||||||
import speiger.src.coreengine.platform.graphics.api.utils.ScissorsManager.IScissorsHandler;
|
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.builder.IVertexBuffer.BufferResult;
|
import speiger.src.coreengine.platform.graphics.api.vertex.builder.IVertexBuffer.BufferResult;
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.builder.IVertexBuilder;
|
import speiger.src.coreengine.platform.graphics.api.vertex.builder.IVertexBuilder;
|
||||||
import speiger.src.coreengine.platform.graphics.api.vertex.builder.VertexBuilder;
|
import speiger.src.coreengine.platform.graphics.api.vertex.builder.VertexBuilder;
|
||||||
@@ -33,10 +40,55 @@ public class UIRenderer implements IUIRenderer {
|
|||||||
int currentComponent = 0;
|
int currentComponent = 0;
|
||||||
ShaderPipeline currentPipeline;
|
ShaderPipeline currentPipeline;
|
||||||
SampledTexture currentTexture;
|
SampledTexture currentTexture;
|
||||||
|
UIDrawer lastDrawer;
|
||||||
ScissorsManager clippingManager = new ScissorsManager(64, ScissorsManager.NoOp.INSTANCE);
|
ScissorsManager clippingManager = new ScissorsManager(64, ScissorsManager.NoOp.INSTANCE);
|
||||||
|
DynamicMesh mesh;
|
||||||
|
|
||||||
public UIRenderer(GraphicsDevice device) {
|
public UIRenderer(GraphicsDevice device) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
|
builder.withAutoAlign();
|
||||||
|
mesh = device.createDynamicMesh(DynamicMesh.builder().autogenerate().bufferState(0, BufferState.STREAM_DRAW));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endFrame() {
|
||||||
|
draws.sort(Comparator.comparingInt(UIDraw::currentLayer).thenComparingInt(UIDraw::componentIndex));
|
||||||
|
mesh.buffer(0).set(builder.memoryPointer(), builder.totalStoredBytes(), BufferOwner.KEPT);
|
||||||
|
GraphicsCommandBuffer buffer = device.createCommandBuffer(ExecutionType.IMMEDIATE);
|
||||||
|
buffer.begin();
|
||||||
|
buffer.mesh(mesh);
|
||||||
|
for(int i = 0,m=draws.size();i<m;i++) {
|
||||||
|
UIDraw draw = draws.get(i);
|
||||||
|
BufferResult result = draw.result();
|
||||||
|
if(draw.drawer != null) {
|
||||||
|
draw.drawer.setupExtra(buffer);
|
||||||
|
buffer.mesh(mesh);
|
||||||
|
}
|
||||||
|
if(draw.texture() != null) buffer.texture(0, draw.texture());
|
||||||
|
buffer.pipeline(draw.pipeline());
|
||||||
|
boolean pop = false;
|
||||||
|
Vec4i scissors = draw.scissors();
|
||||||
|
if(scissors != Vec4i.MINUS_ONE) {
|
||||||
|
pop = true;
|
||||||
|
buffer.pushScissors(scissors.x(), scissors.y(), scissors.z() - scissors.x(), scissors.w() - scissors.y());
|
||||||
|
}
|
||||||
|
buffer.drawArrays(result.startVertex(), result.vertexCount());
|
||||||
|
if(pop) buffer.popScissors();
|
||||||
|
}
|
||||||
|
buffer.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beginFrame() {
|
||||||
|
builder.reset();
|
||||||
|
draws.clear();
|
||||||
|
layers.clear();
|
||||||
|
windowLayer = 1;
|
||||||
|
currentComponent = 0;
|
||||||
|
lastDrawer = null;
|
||||||
|
currentPipeline = null;
|
||||||
|
currentTexture = null;
|
||||||
|
clippingManager.clear();
|
||||||
|
matrix.popRoot();
|
||||||
|
matrix.setIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,11 +98,13 @@ public class UIRenderer implements IUIRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushClip(IGuiBox box) {
|
public void pushClip(IGuiBox box) {
|
||||||
|
flushDraw();
|
||||||
clippingManager.push(Math.round(box.getMinX()), Math.round(box.getMinY()), Math.round(box.getWidth()), Math.round(box.getHeight()));
|
clippingManager.push(Math.round(box.getMinX()), Math.round(box.getMinY()), Math.round(box.getWidth()), Math.round(box.getHeight()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void popClip() {
|
public void popClip() {
|
||||||
|
flushDraw();
|
||||||
clippingManager.pop();
|
clippingManager.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,20 +185,6 @@ public class UIRenderer implements IUIRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Idea:
|
|
||||||
* public class DrawObject {
|
|
||||||
* int windowLayer;
|
|
||||||
* int componentLayer;
|
|
||||||
* ShaderPipeline pipeline;
|
|
||||||
* Int2ObjectMap<SampledTexture> textures;
|
|
||||||
* vec4 scissors;
|
|
||||||
* byte[] vertexData;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* We pregenerate the draw call
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawLine(float startX, float startY, float endX, float endY, float lineWidth, int color) {
|
public void drawLine(float startX, float startY, float endX, float endY, float lineWidth, int color) {
|
||||||
ensureType(UIConstants.GUI, null);
|
ensureType(UIConstants.GUI, null);
|
||||||
@@ -225,8 +265,9 @@ public class UIRenderer implements IUIRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawCustom(UIDrawer drawer) {
|
public void drawCustom(UIDrawer drawer) {
|
||||||
//TDOO ensure the draw type isn't present
|
ensureType(drawer.pipeline(), drawer.texture());
|
||||||
drawer.buildVertecies(builder, matrix);
|
drawer.buildVertecies(builder, matrix);
|
||||||
|
if(drawer.requiresSpecialArgs()) lastDrawer = drawer;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void drawQuad(float minX, float minY, float maxX, float maxY, float xOff, float yOff, int color) {
|
protected void drawQuad(float minX, float minY, float maxX, float maxY, float xOff, float yOff, int color) {
|
||||||
@@ -243,18 +284,25 @@ public class UIRenderer implements IUIRenderer {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void ensureType(ShaderPipeline pipeline, SampledTexture texture) {
|
protected void ensureType(ShaderPipeline pipeline, @Nullable SampledTexture texture) {
|
||||||
if(currentPipeline == pipeline && currentTexture == texture) return;
|
currentComponent++;
|
||||||
if(builder.hasVertecies()) {
|
if(currentPipeline == pipeline && currentTexture == texture && lastDrawer == null) return;
|
||||||
draws.add(new UIDraw(currentPipeline, currentTexture, builder.finish()));
|
flushDraw();
|
||||||
}
|
|
||||||
currentPipeline = pipeline;
|
currentPipeline = pipeline;
|
||||||
currentTexture = texture;
|
currentTexture = texture;
|
||||||
|
lastDrawer = null;
|
||||||
|
builder.start(pipeline.rasterizer().mode(), pipeline.attributes().get(0).layout());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected record UIDraw(ShaderPipeline pipeline, SampledTexture texture, BufferResult result) {}
|
private void flushDraw() {
|
||||||
|
if(builder.hasVertecies()) {
|
||||||
|
draws.add(new UIDraw(currentPipeline, currentTexture, builder.finish(), clippingManager.top(), lastDrawer, layers.isEmpty() ? 0 : layers.top().currentLayer(), currentComponent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class WindowLayer {
|
protected record UIDraw(ShaderPipeline pipeline, @Nullable SampledTexture texture, BufferResult result, Vec4i scissors, @Nullable UIDrawer drawer, int currentLayer, int componentIndex) {}
|
||||||
|
|
||||||
|
class WindowLayer {
|
||||||
final int layer;
|
final int layer;
|
||||||
IntStack stack = new IntArrayList();
|
IntStack stack = new IntArrayList();
|
||||||
int currentLayer = 1;
|
int currentLayer = 1;
|
||||||
@@ -271,7 +319,7 @@ public class UIRenderer implements IUIRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int currentLayer() {
|
public int currentLayer() {
|
||||||
return BitUtil.toInt(layer, stack.isEmpty() ? 0 : stack.top());
|
return BitUtil.toInt(stack.isEmpty() ? 0 : stack.top(), layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ public class MathUtils {
|
|||||||
return Math.signum(value);
|
return Math.signum(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int roundAlign(int value, int alignment) {
|
||||||
|
if(alignment == 0) return value;
|
||||||
|
int r = value % alignment;
|
||||||
|
return r == 0 ? value : value + (alignment - r);
|
||||||
|
}
|
||||||
|
|
||||||
public static int sub(int key, int value) {
|
public static int sub(int key, int value) {
|
||||||
return key - value;
|
return key - value;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user