Skip to content

Commit 762e058

Browse files
committed
Emulate MDI if not present for Sodium
1 parent d4c4781 commit 762e058

4 files changed

Lines changed: 47 additions & 13 deletions

File tree

src/main/java/git/artdeell/artvk/Vk11Device.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class Vk11Device implements GpuDeviceBackend {
4747
private final Map<ShaderCompilationKey, Vk11IntermediaryShaderModule> shaderCache = new HashMap<>();
4848
private final Vk11Instance instance;
4949
private final VkDevice vkDevice;
50+
private final Vk11Features realFeatures;
5051
private final IntVMA vmaObj;
5152
private final long vma;
5253
private final Vk11GlslCompiler glslCompiler = new Vk11GlslCompiler();
@@ -61,16 +62,16 @@ public class Vk11Device implements GpuDeviceBackend {
6162
private final Vk11FramebufferCache framebufferCache;
6263

6364
public Vk11Device(
64-
final ShaderSource defaultShaderSource,
65-
final Vk11Instance instance,
66-
final Vk11PhysicalDevice physicalDevice,
67-
final Set<String> enabledDeviceExtensions,
68-
final VkDevice vkDevice,
69-
final IntVMA vma
65+
final ShaderSource defaultShaderSource,
66+
final Vk11Instance instance,
67+
final Vk11PhysicalDevice physicalDevice,
68+
final Set<String> enabledDeviceExtensions,
69+
final VkDevice vkDevice,
70+
final IntVMA vma
7071
) {
7172
this.defaultShaderSource = defaultShaderSource;
7273
this.instance = instance;
73-
this.vkDevice = vkDevice;
74+
this.vkDevice = vkDevice;
7475
this.vmaObj = vma;
7576
this.vma = vmaObj.ptr;
7677
Set<String> extensionNames = new HashSet<>();
@@ -91,7 +92,9 @@ public Vk11Device(
9192
hasAnisotropy = features.samplerAnisotropy();
9293
hasAttributeDivisor = enabledDeviceExtensions.contains("VK_EXT_vertex_attribute_divisor");
9394

94-
if(!hasFillModeNonSolid) ArtVK.LOGGER.warn("Device does not support fillModeNonSolid, wireframe rendering won't work");
95+
this.realFeatures = new Vk11Features(features.multiDrawIndirect());
96+
97+
if(!hasFillModeNonSolid) ArtVK.LOGGER.warn("Device does not support fillModeNonSolid, wireframe rendering won't work");
9598

9699
this.deviceInfo = new DeviceInfo(
97100
physicalDevice.deviceName(),
@@ -108,7 +111,7 @@ public Vk11Device(
108111
Integer.MAX_VALUE,
109112
limits.maxColorAttachments()
110113
),
111-
new DeviceFeatures(true, enabledDeviceExtensions.contains("VK_EXT_multi_draw"), false, features.multiDrawIndirect(), true, true, true),
114+
new DeviceFeatures(true, enabledDeviceExtensions.contains("VK_EXT_multi_draw"), false, true, true, true, true),
112115
Collections.unmodifiableSet(extensionNames),
113116
new HintsAndWorkarounds(false, false),
114117
physicalDevice.deviceType()
@@ -166,6 +169,9 @@ public Vk11Instance instance() {
166169
public VkDevice vkDevice() {
167170
return this.vkDevice;
168171
}
172+
public Vk11Features realFeatures(){
173+
return this.realFeatures;
174+
}
169175

170176
public Vk11Queue graphicsQueue() {
171177
return this.graphicsQueue;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package git.artdeell.artvk;
2+
3+
// Yes, it sucks, but we can't store emulated features inside real DeviceFeatures
4+
public record Vk11Features(
5+
boolean multiDrawIndirect
6+
) {}

src/main/java/git/artdeell/artvk/Vk11RenderPass.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.mojang.blaze3d.systems.GpuQueryPool;
1010
import com.mojang.blaze3d.systems.RenderPass;
1111
import com.mojang.blaze3d.systems.RenderPassBackend;
12+
import com.mojang.blaze3d.systems.RenderSystem;
1213
import com.mojang.blaze3d.textures.GpuSampler;
1314
import com.mojang.blaze3d.textures.GpuTextureView;
1415
import java.nio.IntBuffer;
@@ -229,9 +230,19 @@ public void multiDrawIndexed(final @NotNull PointerBuffer firstIndexOffsets, fin
229230
public void drawIndexedIndirect(final @NotNull GpuBufferSlice commands, final int drawCount) {
230231
if (pipeline != null && pipeline.isValid()) {
231232
pushDescriptors();
232-
VK10.vkCmdDrawIndexedIndirect(
233-
commandBuffer(), ((Vk11GpuBuffer)commands.buffer()).vkBuffer(), commands.offset(), drawCount, VkDrawIndexedIndirectCommand.SIZEOF
234-
);
233+
long buf = ((Vk11GpuBuffer)commands.buffer()).vkBuffer();
234+
if(device.realFeatures().multiDrawIndirect())
235+
VK10.vkCmdDrawIndexedIndirect(
236+
commandBuffer(), buf, commands.offset(), drawCount, VkDrawIndexedIndirectCommand.SIZEOF
237+
);
238+
else {
239+
// Uh oh! Looping through the draws...
240+
long offset = commands.offset();
241+
int stride = VkDrawIndexedIndirectCommand.SIZEOF;
242+
for(int i = 0; i < drawCount; i++){
243+
VK10.vkCmdDrawIndexedIndirect(commandBuffer(), buf, offset + (long) i *stride, 1, stride);
244+
}
245+
}
235246
} else {
236247
throw new IllegalStateException("Pipeline is missing or not valid");
237248
}
@@ -288,7 +299,16 @@ public void multiDraw(final @NotNull IntBuffer firstVertices, final @NotNull Int
288299
public void drawIndirect(final @NotNull GpuBufferSlice commands, final int drawCount) {
289300
if (pipeline != null && pipeline.isValid()) {
290301
pushDescriptors();
291-
VK10.vkCmdDrawIndirect(commandBuffer(), ((Vk11GpuBuffer)commands.buffer()).vkBuffer(), commands.offset(), drawCount, VkDrawIndirectCommand.SIZEOF);
302+
long buf = ((Vk11GpuBuffer)commands.buffer()).vkBuffer();
303+
if(device.realFeatures().multiDrawIndirect())
304+
VK10.vkCmdDrawIndirect(commandBuffer(), buf, commands.offset(), drawCount, VkDrawIndirectCommand.SIZEOF);
305+
else {
306+
long offset = commands.offset();
307+
int stride = VkDrawIndirectCommand.SIZEOF;
308+
for(int i = 0; i < drawCount; i++){
309+
VK10.vkCmdDrawIndirect(commandBuffer(), buf, offset + (long) i *stride, 1, stride);
310+
}
311+
}
292312
} else {
293313
throw new IllegalStateException("Pipeline is missing or not valid");
294314
}

src/main/java/git/artdeell/compat/sodium/DrawBackendMixin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ private static void injectBackend(CallbackInfoReturnable<DrawBackend> cir){
2121
if(((GpuDeviceAccessor) device).sodium$getBackend() instanceof Vk11Device){
2222
if(device.getDeviceInfo().features().multiDrawDirectInterleaved())
2323
cir.setReturnValue(DrawBackend.VK_MULTIDRAW);
24+
// Upstream Sodium uses MDI here, but we will check for generic indirect draw
25+
// MDI is emulated on the backend side
2426
else if(device.getDeviceInfo().features().drawIndirect())
2527
cir.setReturnValue(DrawBackend.VK_INDIRECT);
2628
else throw new IllegalStateException("Selected Vulkan device does not support neither multidraw nor indirect draw backends. Sodium might be unsupported on this device");

0 commit comments

Comments
 (0)