Skip to content

Commit b044f06

Browse files
committed
Extend and refactor sampler management
1 parent 69f6b76 commit b044f06

6 files changed

Lines changed: 244 additions & 149 deletions

File tree

src/main/java/net/vulkanmod/gl/VkGlRenderbuffer.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,34 @@ void updateSampler() {
159159
if (vulkanImage == null)
160160
return;
161161

162-
byte samplerFlags = magFilter == GL11.GL_LINEAR ? SamplerManager.LINEAR_FILTERING_BIT : 0;
162+
int addressMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
163+
int vkMagFilter, vkMinFilter, mipmapMode;
163164

164-
samplerFlags |= switch (minFilter) {
165-
case GL11.GL_LINEAR_MIPMAP_LINEAR ->
166-
SamplerManager.USE_MIPMAPS_BIT | SamplerManager.MIPMAP_LINEAR_FILTERING_BIT;
167-
case GL11.GL_NEAREST_MIPMAP_NEAREST -> SamplerManager.USE_MIPMAPS_BIT;
168-
default -> 0;
165+
switch (minFilter) {
166+
case GL11.GL_LINEAR_MIPMAP_LINEAR, GL11.GL_LINEAR -> {
167+
vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
168+
}
169+
case GL11.GL_LINEAR_MIPMAP_NEAREST -> {
170+
vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
171+
}
172+
case GL11.GL_NEAREST_MIPMAP_NEAREST, GL11.GL_NEAREST -> {
173+
vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
174+
}
175+
case GL11.GL_NEAREST_MIPMAP_LINEAR -> {
176+
vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
177+
}
178+
default -> throw new IllegalStateException("Unexpected min filter value: %d".formatted(minFilter));
179+
}
180+
181+
vkMagFilter = switch (magFilter) {
182+
case GL11.GL_LINEAR -> VK_FILTER_LINEAR;
183+
case GL11.GL_NEAREST -> VK_FILTER_NEAREST;
184+
default -> throw new IllegalStateException("Unexpected mag filter value: %d".formatted(magFilter));
169185
};
170186

171-
vulkanImage.updateTextureSampler(maxLod, samplerFlags);
187+
long sampler = SamplerManager.getSampler(addressMode, addressMode, vkMinFilter, vkMagFilter, mipmapMode, maxLod, false, 0, -1);
188+
189+
vulkanImage.setSampler(sampler);
172190
}
173191

174192
private void uploadImage(ByteBuffer pixels) {

src/main/java/net/vulkanmod/gl/VkGlTexture.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public static VkGlTexture getBoundTexture() {
279279
boolean needsUpdate = false;
280280
int maxLevel = 0;
281281
int maxLod = 0;
282-
int minFilter, magFilter = GL11.GL_LINEAR;
282+
int minFilter = GL11.GL_NEAREST, magFilter = GL11.GL_NEAREST;
283283

284284
boolean clamp = true;
285285

@@ -340,17 +340,34 @@ void updateSampler() {
340340
if (vulkanImage == null)
341341
return;
342342

343-
byte samplerFlags;
344-
samplerFlags = clamp ? SamplerManager.CLAMP_BIT : 0;
345-
samplerFlags |= magFilter == GL11.GL_LINEAR ? SamplerManager.LINEAR_FILTERING_BIT : 0;
343+
int addressMode = clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT;
344+
int vkMagFilter, vkMinFilter, mipmapMode;
346345

347-
samplerFlags |= switch (minFilter) {
348-
case GL11.GL_LINEAR_MIPMAP_LINEAR -> SamplerManager.USE_MIPMAPS_BIT | SamplerManager.MIPMAP_LINEAR_FILTERING_BIT;
349-
case GL11.GL_NEAREST_MIPMAP_NEAREST -> SamplerManager.USE_MIPMAPS_BIT;
350-
default -> 0;
346+
switch (minFilter) {
347+
case GL11.GL_LINEAR_MIPMAP_LINEAR, GL11.GL_LINEAR -> {
348+
vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
349+
}
350+
case GL11.GL_LINEAR_MIPMAP_NEAREST -> {
351+
vkMinFilter = VK_FILTER_LINEAR; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
352+
}
353+
case GL11.GL_NEAREST_MIPMAP_NEAREST, GL11.GL_NEAREST -> {
354+
vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
355+
}
356+
case GL11.GL_NEAREST_MIPMAP_LINEAR -> {
357+
vkMinFilter = VK_FILTER_NEAREST; mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
358+
}
359+
default -> throw new IllegalStateException("Unexpected min filter value: %d".formatted(minFilter));
360+
}
361+
362+
vkMagFilter = switch (magFilter) {
363+
case GL11.GL_LINEAR -> VK_FILTER_LINEAR;
364+
case GL11.GL_NEAREST -> VK_FILTER_NEAREST;
365+
default -> throw new IllegalStateException("Unexpected mag filter value: %d".formatted(magFilter));
351366
};
352367

353-
vulkanImage.updateTextureSampler(maxLod, samplerFlags);
368+
long sampler = SamplerManager.getSampler(addressMode, addressMode, vkMinFilter, vkMagFilter, mipmapMode, maxLod, false, 0, -1);
369+
370+
vulkanImage.setSampler(sampler);
354371
}
355372

356373
private void uploadSubImage(int level, int xOffset, int yOffset, int width, int height, int format, ByteBuffer pixels) {

src/main/java/net/vulkanmod/render/engine/VkGpuTexture.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ public boolean isClosed() {
5555

5656
public void flushModeChanges() {
5757
if (this.modesDirty) {
58-
byte samplerFlags;
59-
samplerFlags = magFilter == FilterMode.LINEAR ? SamplerManager.LINEAR_FILTERING_BIT : 0;
58+
int maxLod = this.useMipmaps ? this.getMipLevels() - 1 : 0;
6059

61-
// TODO: split min filtering
60+
int magFilterVk = magFilter == FilterMode.LINEAR ? VK10.VK_FILTER_LINEAR : VK10.VK_FILTER_NEAREST;
61+
int minFilterVk = minFilter == FilterMode.LINEAR ? VK10.VK_FILTER_LINEAR : VK10.VK_FILTER_NEAREST;
6262

63-
if (this.useMipmaps) {
64-
samplerFlags |= SamplerManager.USE_MIPMAPS_BIT | SamplerManager.MIPMAP_LINEAR_FILTERING_BIT;
65-
}
63+
long sampler = SamplerManager.getSampler(VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK10.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
64+
minFilterVk, magFilterVk, VK10.VK_SAMPLER_MIPMAP_MODE_LINEAR,
65+
maxLod, false, 0, -1);
6666

67-
glTexture.getVulkanImage().updateTextureSampler(this.getMipLevels(), samplerFlags);
67+
glTexture.getVulkanImage().setSampler(sampler);
6868

6969
this.modesDirty = false;
7070
}

src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import net.vulkanmod.vulkan.Vulkan;
88
import net.vulkanmod.vulkan.device.DeviceManager;
99
import net.vulkanmod.vulkan.queue.Queue;
10+
import net.vulkanmod.vulkan.texture.SamplerManager;
1011
import net.vulkanmod.vulkan.texture.VulkanImage;
1112
import org.lwjgl.system.MemoryStack;
1213
import org.lwjgl.vulkan.*;
@@ -152,7 +153,8 @@ private void createSwapChain() {
152153
long imageView = VulkanImage.createImageView(imageId, this.format, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1);
153154

154155
VulkanImage image = new VulkanImage("Swapchain", imageId, this.format, 1, this.width, this.height, 4, 0, imageView);
155-
image.updateTextureSampler(true, true, false);
156+
long samplerId = SamplerManager.getSampler(true, true, 0);
157+
image.setSampler(samplerId);
156158
this.swapChainImages.add(image);
157159
}
158160
}
Lines changed: 142 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package net.vulkanmod.vulkan.texture;
22

3-
import it.unimi.dsi.fastutil.shorts.Short2LongMap;
4-
import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap;
3+
import it.unimi.dsi.fastutil.objects.Object2LongMap;
4+
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
55
import net.vulkanmod.vulkan.device.DeviceManager;
6-
import org.apache.commons.lang3.Validate;
76
import org.lwjgl.system.MemoryStack;
87
import org.lwjgl.vulkan.VkSamplerCreateInfo;
98
import org.lwjgl.vulkan.VkSamplerReductionModeCreateInfo;
@@ -13,81 +12,86 @@
1312
import static net.vulkanmod.vulkan.Vulkan.getVkDevice;
1413
import static org.lwjgl.system.MemoryStack.stackPush;
1514
import static org.lwjgl.vulkan.VK10.*;
16-
import static org.lwjgl.vulkan.VK12.VK_SAMPLER_REDUCTION_MODE_MAX;
17-
import static org.lwjgl.vulkan.VK12.VK_SAMPLER_REDUCTION_MODE_MIN;
1815

1916
public abstract class SamplerManager {
17+
public static final int ADDRESS_MODE_BITS = 2;
18+
public static final int REDUCTION_MODE_BITS = 2;
19+
20+
public static final int ADDRESS_MODE_U_OFFSET = 0;
21+
public static final int ADDRESS_MODE_V_OFFSET = 2;
22+
public static final int MIN_FILTER_OFFSET = 4;
23+
public static final int MAG_FILTER_OFFSET = 5;
24+
public static final int MIPMAP_MODE_OFFSET = 6;
25+
public static final int ANISOTROPY_OFFSET = 7;
26+
public static final int REDUCTION_MODE_ENABLE_OFFSET = 8;
27+
public static final int REDUCTION_MODE_OFFSET = 9;
28+
2029
static final float MIP_BIAS = -0.5f;
2130

22-
static final Short2LongMap SAMPLERS = new Short2LongOpenHashMap();
31+
static final Object2LongMap<SamplerInfo> SAMPLERS = new Object2LongOpenHashMap<>();
32+
33+
public static long getSampler(boolean clamp, boolean linearFiltering, int maxLod) {
34+
return getSampler(clamp, linearFiltering, maxLod, false, 0);
35+
}
36+
37+
public static long getSampler(boolean clamp, boolean linearFiltering, int maxLod, boolean anisotropy, int maxAnisotropy) {
38+
int addressMode = clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT;
39+
int filter = linearFiltering ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
40+
int mipmapMode = linearFiltering ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
41+
42+
return getSampler(addressMode, addressMode, filter, filter, mipmapMode, maxLod, anisotropy, maxAnisotropy, -1);
43+
}
44+
45+
public static long getSampler(int addressModeU, int addressModeV,
46+
int minFilter, int magFilter, int mipmapMode, float maxLod,
47+
boolean anisotropy, float maxAnisotropy, int reductionMode) {
48+
SamplerInfo samplerInfo = new SamplerInfo(addressModeU, addressModeV, minFilter, magFilter, mipmapMode, maxLod, anisotropy, maxAnisotropy, reductionMode);
2349

24-
public static long getTextureSampler(byte maxLod, byte flags) {
25-
short key = (short) (flags | (maxLod << 8));
26-
long sampler = SAMPLERS.getOrDefault(key, 0L);
50+
long sampler = SAMPLERS.getOrDefault(samplerInfo, 0L);
2751

2852
if (sampler == 0L) {
29-
sampler = createTextureSampler(maxLod, flags);
30-
SAMPLERS.put(key, sampler);
53+
sampler = createTextureSampler(samplerInfo);
54+
SAMPLERS.put(samplerInfo, sampler);
3155
}
3256

3357
return sampler;
3458
}
3559

36-
private static long createTextureSampler(byte maxLod, byte flags) {
37-
Validate.isTrue(
38-
(flags & (REDUCTION_MIN_BIT | REDUCTION_MAX_BIT)) != (REDUCTION_MIN_BIT | REDUCTION_MAX_BIT)
39-
);
60+
public static long getDefaultSampler() {
61+
return getSampler(false, false, 0);
62+
}
4063

41-
try (MemoryStack stack = stackPush()) {
64+
private static long createTextureSampler(SamplerInfo sampler) {
65+
int state = sampler.encodedState;
4266

67+
try (MemoryStack stack = stackPush()) {
4368
VkSamplerCreateInfo samplerInfo = VkSamplerCreateInfo.calloc(stack);
4469
samplerInfo.sType(VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
4570

46-
if ((flags & LINEAR_FILTERING_BIT) != 0) {
47-
samplerInfo.magFilter(VK_FILTER_LINEAR);
48-
samplerInfo.minFilter(VK_FILTER_LINEAR);
49-
} else {
50-
samplerInfo.magFilter(VK_FILTER_NEAREST);
51-
samplerInfo.minFilter(VK_FILTER_NEAREST);
52-
}
71+
samplerInfo.magFilter(sampler.getMagFilter());
72+
samplerInfo.minFilter(sampler.getMinFilter());
5373

54-
if ((flags & CLAMP_BIT) != 0) {
55-
samplerInfo.addressModeU(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
56-
samplerInfo.addressModeV(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
57-
samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
58-
} else {
59-
samplerInfo.addressModeU(VK_SAMPLER_ADDRESS_MODE_REPEAT);
60-
samplerInfo.addressModeV(VK_SAMPLER_ADDRESS_MODE_REPEAT);
61-
samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_REPEAT);
62-
}
74+
samplerInfo.addressModeU(sampler.getAddressModeU());
75+
samplerInfo.addressModeV(sampler.getAddressModeV());
76+
samplerInfo.addressModeW(VK_SAMPLER_ADDRESS_MODE_REPEAT);
6377

64-
samplerInfo.anisotropyEnable(false);
65-
//samplerInfo.maxAnisotropy(16.0f);
78+
samplerInfo.anisotropyEnable(sampler.getAnisotropy());
79+
samplerInfo.maxAnisotropy(sampler.getMaxAnisotropy());
6680
samplerInfo.borderColor(VK_BORDER_COLOR_INT_OPAQUE_WHITE);
6781
samplerInfo.unnormalizedCoordinates(false);
6882
samplerInfo.compareEnable(false);
6983
samplerInfo.compareOp(VK_COMPARE_OP_ALWAYS);
7084

71-
if ((flags & USE_MIPMAPS_BIT) == 0) {
72-
samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
73-
samplerInfo.maxLod(0.0F);
74-
samplerInfo.minLod(0.0F);
75-
} else {
76-
if ((flags & MIPMAP_LINEAR_FILTERING_BIT) != 0) {
77-
samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR);
78-
} else {
79-
samplerInfo.mipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
80-
}
81-
samplerInfo.maxLod(maxLod);
82-
samplerInfo.minLod(0.0F);
83-
samplerInfo.mipLodBias(MIP_BIAS);
84-
}
85+
samplerInfo.mipmapMode(sampler.getMipmapMode());
86+
samplerInfo.maxLod(sampler.getMaxLod());
87+
samplerInfo.minLod(0.0F);
88+
samplerInfo.mipLodBias(MIP_BIAS);
8589

86-
//Reduction Mode
87-
if ((flags & (REDUCTION_MAX_BIT | REDUCTION_MIN_BIT)) != 0) {
90+
// Reduction Mode
91+
if (sampler.hasReductionMode()) {
8892
VkSamplerReductionModeCreateInfo reductionModeInfo = VkSamplerReductionModeCreateInfo.calloc(stack);
8993
reductionModeInfo.sType$Default();
90-
reductionModeInfo.reductionMode((flags & REDUCTION_MAX_BIT) != 0 ? VK_SAMPLER_REDUCTION_MODE_MAX : VK_SAMPLER_REDUCTION_MODE_MIN);
94+
reductionModeInfo.reductionMode(sampler.getReductionMode());
9195
samplerInfo.pNext(reductionModeInfo.address());
9296
}
9397

@@ -107,10 +111,91 @@ public static void cleanUp() {
107111
}
108112
}
109113

110-
public static final byte LINEAR_FILTERING_BIT = 0b1;
111-
public static final byte CLAMP_BIT = 0b10;
112-
public static final byte USE_MIPMAPS_BIT = 0b100;
113-
public static final byte MIPMAP_LINEAR_FILTERING_BIT = 0b1000;
114-
public static final byte REDUCTION_MIN_BIT = 0b10000;
115-
public static final byte REDUCTION_MAX_BIT = 0b100000;
114+
public static class SamplerInfo {
115+
final int encodedState;
116+
final int maxLod;
117+
final int maxAnisotropy;
118+
119+
public SamplerInfo() {
120+
this(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
121+
VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
122+
0, false, 0, -1);
123+
}
124+
125+
126+
127+
public SamplerInfo(int addressModeU, int addressModeV, int minFilter, int magFilter, int mipmapMode,
128+
float maxLod, boolean anisotropy, float maxAnisotropy, int reductionMode) {
129+
this.maxLod = (int) maxLod;
130+
this.maxAnisotropy = (int) maxAnisotropy;
131+
132+
int encodedState = (addressModeU & ADDRESS_MODE_BITS) << ADDRESS_MODE_U_OFFSET;
133+
encodedState |= (addressModeV & ADDRESS_MODE_BITS) << ADDRESS_MODE_V_OFFSET;
134+
encodedState |= (minFilter & 1) << MIN_FILTER_OFFSET;
135+
encodedState |= (magFilter & 1) << MAG_FILTER_OFFSET;
136+
encodedState |= (mipmapMode & 1) << MIPMAP_MODE_OFFSET;
137+
encodedState |= ((anisotropy ? 1 : 0) & 1) << ANISOTROPY_OFFSET;
138+
encodedState |= (reductionMode != -1 ? 1 : 0) << REDUCTION_MODE_ENABLE_OFFSET;
139+
encodedState |= (reductionMode & REDUCTION_MODE_BITS) << REDUCTION_MODE_OFFSET;
140+
141+
this.encodedState = encodedState;
142+
}
143+
144+
public int getAddressModeU() {
145+
return (this.encodedState >> ADDRESS_MODE_U_OFFSET) & ADDRESS_MODE_BITS;
146+
}
147+
148+
public int getAddressModeV() {
149+
return (this.encodedState >> ADDRESS_MODE_V_OFFSET) & ADDRESS_MODE_BITS;
150+
}
151+
152+
public int getMinFilter() {
153+
return (this.encodedState >> MIN_FILTER_OFFSET) & 1;
154+
}
155+
156+
public int getMagFilter() {
157+
return (this.encodedState >> MAG_FILTER_OFFSET) & 1;
158+
}
159+
160+
public int getMipmapMode() {
161+
return (this.encodedState >> MIPMAP_MODE_OFFSET) & 1;
162+
}
163+
164+
public boolean getAnisotropy() {
165+
return ((this.encodedState >> ANISOTROPY_OFFSET) & 1) != 0;
166+
}
167+
168+
public boolean hasReductionMode() {
169+
return ((this.encodedState >> REDUCTION_MODE_ENABLE_OFFSET) & 1) != 0;
170+
}
171+
172+
public int getReductionMode() {
173+
return (this.encodedState >> REDUCTION_MODE_OFFSET) & REDUCTION_MODE_BITS;
174+
}
175+
176+
public int getMaxAnisotropy() {
177+
return maxAnisotropy;
178+
}
179+
180+
public int getMaxLod() {
181+
return maxLod;
182+
}
183+
184+
@Override
185+
public boolean equals(Object o) {
186+
if (o == null || getClass() != o.getClass()) return false;
187+
188+
SamplerInfo samplerInfo = (SamplerInfo) o;
189+
return maxLod == samplerInfo.maxLod && maxAnisotropy == samplerInfo.maxAnisotropy && encodedState == samplerInfo.encodedState;
190+
}
191+
192+
@Override
193+
public int hashCode() {
194+
int result = encodedState;
195+
result = 31 * result + maxLod;
196+
result = 31 * result + maxAnisotropy;
197+
return result;
198+
}
199+
}
200+
116201
}

0 commit comments

Comments
 (0)