Skip to content

Commit

Permalink
Add support for video coding queue families
Browse files Browse the repository at this point in the history
  • Loading branch information
knokko committed Dec 30, 2023
1 parent f135f22 commit 3667e4b
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,23 @@ static Result createDevice(BoilerBuilder builder, BoilerInstanceBuilder.Result i
} else queueFamilyPresentSupport[familyIndex] = true;
}

var queueFamilyMapping = builder.queueFamilyMapper.mapQueueFamilies(pQueueFamilies, queueFamilyPresentSupport);
var queueFamilyMapping = builder.queueFamilyMapper.mapQueueFamilies(
pQueueFamilies, enabledExtensions, queueFamilyPresentSupport
);
queueFamilyMapping.validate();

var uniqueQueueFamilies = new HashMap<Integer, float[]>();
// Do presentFamily first so that it will be overwritten by the others if the queue family is shared
uniqueQueueFamilies.put(queueFamilyMapping.presentFamilyIndex(), new float[] { 1f });
uniqueQueueFamilies.put(queueFamilyMapping.graphicsFamilyIndex(), queueFamilyMapping.graphicsPriorities());
uniqueQueueFamilies.put(queueFamilyMapping.computeFamilyIndex(), queueFamilyMapping.computePriorities());
uniqueQueueFamilies.put(queueFamilyMapping.transferFamilyIndex(), queueFamilyMapping.transferPriorities());
uniqueQueueFamilies.put(queueFamilyMapping.graphics().index(), queueFamilyMapping.graphics().priorities());
uniqueQueueFamilies.put(queueFamilyMapping.compute().index(), queueFamilyMapping.compute().priorities());
uniqueQueueFamilies.put(queueFamilyMapping.transfer().index(), queueFamilyMapping.transfer().priorities());
if (queueFamilyMapping.videoEncode() != null) {
uniqueQueueFamilies.put(queueFamilyMapping.videoEncode().index(), queueFamilyMapping.videoEncode().priorities());
}
if (queueFamilyMapping.videoDecode() != null) {
uniqueQueueFamilies.put(queueFamilyMapping.videoDecode().index(), queueFamilyMapping.videoDecode().priorities());
}

var pQueueCreateInfos = VkDeviceQueueCreateInfo.calloc(uniqueQueueFamilies.size(), stack);
int ciQueueIndex = 0;
Expand Down Expand Up @@ -200,11 +208,15 @@ static Result createDevice(BoilerBuilder builder, BoilerInstanceBuilder.Result i
queueFamilyMap.put(entry.getKey(), getQueueFamily(stack, vkDevice, entry.getKey(), entry.getValue().length));
}

int videoEncodeIndex = queueFamilyMapping.videoEncode() != null ? queueFamilyMapping.videoEncode().index() : -1;
int videoDecodeIndex = queueFamilyMapping.videoDecode() != null ? queueFamilyMapping.videoDecode().index() : -1;
queueFamilies = new QueueFamilies(
queueFamilyMap.get(queueFamilyMapping.graphicsFamilyIndex()),
queueFamilyMap.get(queueFamilyMapping.computeFamilyIndex()),
queueFamilyMap.get(queueFamilyMapping.transferFamilyIndex()),
queueFamilyMap.get(queueFamilyMapping.presentFamilyIndex())
queueFamilyMap.get(queueFamilyMapping.graphics().index()),
queueFamilyMap.get(queueFamilyMapping.compute().index()),
queueFamilyMap.get(queueFamilyMapping.transfer().index()),
queueFamilyMap.get(queueFamilyMapping.presentFamilyIndex()),
queueFamilyMap.get(videoEncodeIndex),
queueFamilyMap.get(videoDecodeIndex)
);

var vmaVulkanFunctions = VmaVulkanFunctions.calloc(stack);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,49 @@

import org.lwjgl.vulkan.VkQueueFamilyProperties;

import java.util.Set;

import static org.lwjgl.vulkan.KHRVideoDecodeQueue.VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME;
import static org.lwjgl.vulkan.KHRVideoDecodeQueue.VK_QUEUE_VIDEO_DECODE_BIT_KHR;
import static org.lwjgl.vulkan.KHRVideoEncodeQueue.VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME;
import static org.lwjgl.vulkan.KHRVideoEncodeQueue.VK_QUEUE_VIDEO_ENCODE_BIT_KHR;
import static org.lwjgl.vulkan.VK10.VK_QUEUE_COMPUTE_BIT;
import static org.lwjgl.vulkan.VK10.VK_QUEUE_GRAPHICS_BIT;

public class MinimalQueueFamilyMapper implements QueueFamilyMapper {

@Override
public QueueFamilyMapping mapQueueFamilies(VkQueueFamilyProperties.Buffer queueFamilies, boolean[] presentSupport) {
public QueueFamilyMapping mapQueueFamilies(
VkQueueFamilyProperties.Buffer queueFamilies,
Set<String> deviceExtensions,
boolean[] presentSupport
) {
float[] priorities = { 1f };
int graphicsFamilyIndex = -1;
int computeFamilyIndex = -1;
int presentFamilyIndex = -1;

boolean shouldTryEncode = deviceExtensions.contains(VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
boolean shouldTryDecode = deviceExtensions.contains(VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
int encodeIndex = -1;
int decodeIndex = -1;
for (int familyIndex = 0; familyIndex < queueFamilies.limit(); familyIndex++) {
int queueFlags = queueFamilies.get(familyIndex).queueFlags();
boolean hasEncode = shouldTryEncode && (queueFlags & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0;
boolean hasDecode = shouldTryDecode && (queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0;
if (hasEncode && hasDecode) {
encodeIndex = familyIndex;
decodeIndex = familyIndex;
break;
}

if (encodeIndex == -1 && hasEncode) encodeIndex = familyIndex;
if (decodeIndex == -1 && hasDecode) decodeIndex = familyIndex;
}

var videoEncode = encodeIndex != -1 ? new QueueFamilyAllocation(encodeIndex, priorities) : null;
var videoDecode = decodeIndex != -1 ? new QueueFamilyAllocation(decodeIndex, priorities) : null;

int graphicsIndex = -1;
int computeIndex = -1;
int presentIndex = -1;

for (int familyIndex = 0; familyIndex < queueFamilies.limit(); familyIndex++) {
int queueFlags = queueFamilies.get(familyIndex).queueFlags();
Expand All @@ -21,26 +53,27 @@ public QueueFamilyMapping mapQueueFamilies(VkQueueFamilyProperties.Buffer queueF
boolean hasPresent = presentSupport[familyIndex];

if (hasGraphics && hasCompute && hasPresent) {
return new QueueFamilyMapping(
familyIndex, priorities, familyIndex, priorities, familyIndex, priorities, familyIndex
);
var allocation = new QueueFamilyAllocation(familyIndex, priorities);
return new QueueFamilyMapping(allocation, allocation, allocation, videoEncode, videoDecode, familyIndex);
}

if (graphicsFamilyIndex == -1 && hasGraphics) graphicsFamilyIndex = familyIndex;
if (computeFamilyIndex == -1 && hasCompute) computeFamilyIndex = familyIndex;
if (graphicsIndex == -1 && hasGraphics) graphicsIndex = familyIndex;
if (computeIndex == -1 && hasCompute) computeIndex = familyIndex;
if (hasGraphics && hasCompute) {
graphicsFamilyIndex = familyIndex;
computeFamilyIndex = familyIndex;
graphicsIndex = familyIndex;
computeIndex = familyIndex;
}

if (presentFamilyIndex == -1 && hasPresent) presentFamilyIndex = familyIndex;
if ((hasGraphics || hasCompute) && hasPresent) presentFamilyIndex = familyIndex;
if (presentIndex == -1 && hasPresent) presentIndex = familyIndex;
if ((hasGraphics || hasCompute) && hasPresent) presentIndex = familyIndex;
}


return new QueueFamilyMapping(
graphicsFamilyIndex, priorities,
computeFamilyIndex, priorities,
graphicsFamilyIndex, priorities, presentFamilyIndex
new QueueFamilyAllocation(graphicsIndex, priorities),
new QueueFamilyAllocation(computeIndex, priorities),
new QueueFamilyAllocation(graphicsIndex, priorities),
videoEncode, videoDecode, presentIndex
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.github.knokko.boiler.builder.queue;

public record QueueFamilyAllocation(int index, float[] priorities) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

import org.lwjgl.vulkan.VkQueueFamilyProperties;

import java.util.Set;

@FunctionalInterface
public interface QueueFamilyMapper {

QueueFamilyMapping mapQueueFamilies(VkQueueFamilyProperties.Buffer queueFamilies, boolean[] presentSupport);
QueueFamilyMapping mapQueueFamilies(
VkQueueFamilyProperties.Buffer queueFamilies,
Set<String> deviceExtensions,
boolean[] presentSupport
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,45 @@
import java.util.Arrays;

public record QueueFamilyMapping(
int graphicsFamilyIndex, float[] graphicsPriorities,
int computeFamilyIndex, float[] computePriorities,
int transferFamilyIndex, float[] transferPriorities,
QueueFamilyAllocation graphics,
QueueFamilyAllocation compute,
QueueFamilyAllocation transfer,
QueueFamilyAllocation videoEncode,
QueueFamilyAllocation videoDecode,
int presentFamilyIndex
) {

public void validate() throws IllegalStateException {
validateFamilyPriorities(graphicsFamilyIndex, computeFamilyIndex, graphicsPriorities, computePriorities, "graphics", "compute");
validateFamilyPriorities(graphicsFamilyIndex, transferFamilyIndex, graphicsPriorities, transferPriorities, "graphics", "transfer");
validateFamilyPriorities(computeFamilyIndex, transferFamilyIndex, computePriorities, transferPriorities, "compute", "transfer");
validateFamilyPriorities(graphics, compute, "graphics", "compute");
validateFamilyPriorities(graphics, transfer, "graphics", "transfer");
validateFamilyPriorities(compute, transfer, "compute", "transfer");
if (videoEncode != null) {
validateFamilyPriorities(graphics, videoEncode, "graphics", "videoEncode");
validateFamilyPriorities(compute, videoEncode, "compute", "videoEncode");
validateFamilyPriorities(transfer, videoEncode, "transfer", "videoEncode");
}
if (videoDecode != null) {
validateFamilyPriorities(graphics, videoDecode, "graphics", "videoDecode");
validateFamilyPriorities(compute, videoDecode, "compute", "videoDecode");
validateFamilyPriorities(transfer, videoDecode, "transfer", "videoDecode");
}
if (videoEncode != null && videoDecode != null) {
validateFamilyPriorities(videoEncode, videoDecode, "videoEncode", "videoDecode");
}
}

private void validateFamilyPriorities(
int index1, int index2, float[] priorities1, float[] priorities2, String name1, String name2
QueueFamilyAllocation allocation1, QueueFamilyAllocation allocation2, String name1, String name2
) throws IllegalStateException {
if (priorities1 == null || priorities2 == null) throw new IllegalStateException("Priorities are null");
if (index1 == index2 && !Arrays.equals(priorities1, priorities2)) {
if (allocation1.priorities() == null || allocation2.priorities() == null) {
throw new IllegalStateException("Priorities are null");
}
if (allocation1.index() == allocation2.index() &&
!Arrays.equals(allocation1.priorities(), allocation2.priorities())) {
throw new IllegalStateException(String.format(
"%sIndex == %sIndex (%d), but %sPriorities (%s) != %sPriorities(%s)",
name1, name2, index1, name1, Arrays.toString(priorities1), name2, Arrays.toString(priorities2)
name1, name2, allocation1.index(), name1, Arrays.toString(allocation1.priorities()),
name2, Arrays.toString(allocation2.priorities())
));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.knokko.boiler.queue;

public record QueueFamilies(
QueueFamily graphics, QueueFamily compute, QueueFamily transfer, QueueFamily present
QueueFamily graphics, QueueFamily compute,
QueueFamily transfer, QueueFamily present,
QueueFamily videoEncode, QueueFamily videoDecode
) { }
Loading

0 comments on commit 3667e4b

Please sign in to comment.