Skip to content

Commit

Permalink
HelloXR sample: draw triangle on the floor
Browse files Browse the repository at this point in the history
  • Loading branch information
knokko committed Dec 5, 2023
1 parent ebb3c9c commit a1e4ba1
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 3 deletions.
186 changes: 183 additions & 3 deletions samples/src/main/java/com/github/knokko/boiler/samples/HelloXR.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.github.knokko.boiler.builder.instance.ValidationFeatures;
import com.github.knokko.boiler.builder.xr.BoilerXrBuilder;
import com.github.knokko.boiler.commands.CommandRecorder;
import com.github.knokko.boiler.pipelines.GraphicsPipelineBuilder;
import com.github.knokko.boiler.pipelines.ShaderInfo;
import com.github.knokko.boiler.sync.WaitSemaphore;
import org.joml.Matrix4f;
import org.lwjgl.PointerBuffer;
Expand All @@ -18,6 +20,7 @@
import static java.lang.Thread.sleep;
import static org.lwjgl.openxr.XR10.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.memFloatBuffer;
import static org.lwjgl.vulkan.KHRCreateRenderpass2.VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME;
import static org.lwjgl.vulkan.KHRDepthStencilResolve.VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME;
import static org.lwjgl.vulkan.KHRDynamicRendering.*;
Expand Down Expand Up @@ -46,19 +49,28 @@ public static void main(String[] args) throws InterruptedException {
var dynamicRendering = VkPhysicalDeviceDynamicRenderingFeaturesKHR.calloc(stack);
dynamicRendering.sType$Default();

var multiview = VkPhysicalDeviceMultiviewFeaturesKHR.calloc(stack);
multiview.sType$Default();

var features2 = VkPhysicalDeviceFeatures2KHR.calloc(stack);
features2.sType$Default();
features2.pNext(dynamicRendering);
features2.pNext(multiview);

vkGetPhysicalDeviceFeatures2KHR(physicalDevice, features2);
return dynamicRendering.dynamicRendering();
return dynamicRendering.dynamicRendering() && multiview.multiview();
})
.beforeDeviceCreation((ciDevice, physicalDevice, stack) -> {
var dynamicRendering = VkPhysicalDeviceDynamicRenderingFeaturesKHR.calloc(stack);
dynamicRendering.sType$Default();
dynamicRendering.dynamicRendering(true);

var multiview = VkPhysicalDeviceMultiviewFeaturesKHR.calloc(stack);
multiview.sType$Default();
multiview.multiview(true);

ciDevice.pNext(dynamicRendering);
ciDevice.pNext(multiview);
})
.xr(new BoilerXrBuilder())
.build();
Expand Down Expand Up @@ -125,6 +137,150 @@ public static void main(String[] args) throws InterruptedException {
var commandBuffer = boiler.commands.createPrimaryBuffers(commandPool, 1, "Drawing")[0];
var fence = boiler.sync.createFences(false, 1, "Drawing")[0];

int vertexSize = (3 + 3) * 4;
var vertexBuffer = boiler.buffers.createMapped(
3 * vertexSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, "VertexBuffer"
);
var hostVertexBuffer = memFloatBuffer(vertexBuffer.hostAddress(), 3 * 6);
hostVertexBuffer.put(-1f).put(0f).put(-1f); // vertex1.position = (-1, 0, -1)
hostVertexBuffer.put(1f).put(0f).put(0f); // vertex1.color = red
hostVertexBuffer.put(1f).put(0f).put(-1f); // vertex2.position = (1, 0, -1)
hostVertexBuffer.put(0f).put(1f).put(0f); // vertex2.color = green
hostVertexBuffer.put(0f).put(0f).put(1f); // vertex3.position = (0, 0, 1)
hostVertexBuffer.put(0f).put(0f).put(1f); // vertex3.color = blue

var matrixBuffer = boiler.buffers.createMapped(
2 * 64, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, "MatrixBuffer"
);

long descriptorSetLayout;
long descriptorPool;
long descriptorSet;
long pipelineLayout;
long graphicsPipeline;
try (var stack = stackPush()) {

var layoutBindings = VkDescriptorSetLayoutBinding.calloc(1, stack);
var matricesBinding = layoutBindings.get(0);
matricesBinding.binding(0);
matricesBinding.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
matricesBinding.descriptorCount(1);
matricesBinding.stageFlags(VK_SHADER_STAGE_VERTEX_BIT);
matricesBinding.pImmutableSamplers(null);

descriptorSetLayout = boiler.descriptors.createLayout(stack, layoutBindings, "MatricesLayout");

var poolSizes = VkDescriptorPoolSize.calloc(1, stack);
poolSizes.type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
poolSizes.descriptorCount(1);

var ciDescriptorPool = VkDescriptorPoolCreateInfo.calloc(stack);
ciDescriptorPool.sType$Default();
ciDescriptorPool.flags(0);
ciDescriptorPool.maxSets(1);
ciDescriptorPool.pPoolSizes(poolSizes);

var pDescriptorPool = stack.callocLong(1);
assertVkSuccess(vkCreateDescriptorPool(
boiler.vkDevice(), ciDescriptorPool, null, pDescriptorPool
), "CreateDescriptorPool", "MatricesPool");
descriptorPool = pDescriptorPool.get(0);
descriptorSet = boiler.descriptors.allocate(
stack, 1, descriptorPool, "MatricesSet", descriptorSetLayout
)[0];

var descriptorWrites = VkWriteDescriptorSet.calloc(1, stack);
var matrixWrite = descriptorWrites.get(0);
matrixWrite.sType$Default();
matrixWrite.dstSet(descriptorSet);
matrixWrite.dstBinding(0);
matrixWrite.dstArrayElement(0);
matrixWrite.descriptorCount(1);
matrixWrite.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
matrixWrite.pBufferInfo(boiler.descriptors.bufferInfo(stack, matrixBuffer.asBuffer()));

vkUpdateDescriptorSets(boiler.vkDevice(), descriptorWrites, null);

pipelineLayout = boiler.pipelines.createLayout(
stack, null, "SimplePipelineLayout", descriptorSetLayout
);
var vertexShader = boiler.pipelines.createShaderModule(
stack, "com/github/knokko/boiler/samples/graphics/xr.vert.spv", "VertexShader"
);
var fragmentShader = boiler.pipelines.createShaderModule(
stack, "com/github/knokko/boiler/samples/graphics/triangle.frag.spv", "FragmentShader"
);

var vertexBindings = VkVertexInputBindingDescription.calloc(1, stack);
vertexBindings.binding(0);
vertexBindings.stride(vertexSize);
vertexBindings.inputRate(VK_VERTEX_INPUT_RATE_VERTEX);

var vertexAttributes = VkVertexInputAttributeDescription.calloc(2, stack);
var positionAttribute = vertexAttributes.get(0);
positionAttribute.location(0);
positionAttribute.binding(0);
positionAttribute.format(VK_FORMAT_R32G32B32_SFLOAT);
positionAttribute.offset(0);
var colorAttribute = vertexAttributes.get(1);
colorAttribute.location(1);
colorAttribute.binding(0);
colorAttribute.format(VK_FORMAT_R32G32B32_SFLOAT);
colorAttribute.offset(12);

var ciVertexInput = VkPipelineVertexInputStateCreateInfo.calloc(stack);
ciVertexInput.sType$Default();
ciVertexInput.pVertexBindingDescriptions(vertexBindings);
ciVertexInput.pVertexAttributeDescriptions(vertexAttributes);

var viewportSize = VkViewport.calloc(1, stack);
viewportSize.x(0f);
viewportSize.y(0f);
viewportSize.width(width);
viewportSize.height(height);
viewportSize.minDepth(0f);
viewportSize.maxDepth(1f);

var scissorSize = VkRect2D.calloc(1, stack);
scissorSize.offset().set(0, 0);
scissorSize.extent().set(width, height);

var ciViewport = VkPipelineViewportStateCreateInfo.calloc(stack);
ciViewport.sType$Default();
ciViewport.viewportCount(1); // TODO Maybe 2?
ciViewport.pViewports(viewportSize);
ciViewport.scissorCount(1);
ciViewport.pScissors(scissorSize);

var dynamicRendering = VkPipelineRenderingCreateInfoKHR.calloc(stack);
dynamicRendering.sType$Default();
dynamicRendering.viewMask(3); // TODO Configure?
dynamicRendering.colorAttachmentCount(1);
dynamicRendering.pColorAttachmentFormats(stack.ints((int) swapchainFormat));
dynamicRendering.depthAttachmentFormat(depthFormat);
dynamicRendering.stencilAttachmentFormat(VK_FORMAT_UNDEFINED);

var pipelineBuilder = new GraphicsPipelineBuilder(boiler, stack);
pipelineBuilder.shaderStages(
new ShaderInfo(VK_SHADER_STAGE_VERTEX_BIT, vertexShader, null),
new ShaderInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShader, null)
);
pipelineBuilder.ciPipeline.pVertexInputState(ciVertexInput);
pipelineBuilder.simpleInputAssembly();
pipelineBuilder.ciPipeline.pViewportState(ciViewport);
pipelineBuilder.simpleRasterization(VK_CULL_MODE_NONE); // TODO Cull back
pipelineBuilder.noMultisampling();
pipelineBuilder.simpleDepthStencil(VK_COMPARE_OP_LESS_OR_EQUAL);
pipelineBuilder.ciPipeline.layout(pipelineLayout);
pipelineBuilder.noColorBlending(1);
pipelineBuilder.ciPipeline.pNext(dynamicRendering);

graphicsPipeline = pipelineBuilder.build("SimplePipeline");

vkDestroyShaderModule(boiler.vkDevice(), vertexShader, null);
vkDestroyShaderModule(boiler.vkDevice(), fragmentShader, null);
}

int[] sessionState = { XR_SESSION_STATE_IDLE };
boolean isSessionRunning = false;
boolean didRequestExit = false;
Expand Down Expand Up @@ -159,7 +315,8 @@ public static void main(String[] args) throws InterruptedException {
}

if (sessionState[0] == XR_SESSION_STATE_IDLE) {
sleep(500);
//noinspection BusyWait
sleep(500); // TODO Configure
continue;
}

Expand Down Expand Up @@ -269,11 +426,27 @@ public static void main(String[] args) throws InterruptedException {
dynamicRenderingInfo.renderArea().offset().set(0, 0);
dynamicRenderingInfo.renderArea().extent().set(width, height);
dynamicRenderingInfo.layerCount(2);
dynamicRenderingInfo.viewMask(0);
dynamicRenderingInfo.viewMask(3); // TODO Configure?
dynamicRenderingInfo.pColorAttachments(colorAttachments);

var commands = CommandRecorder.begin(commandBuffer, boiler, stack, "Drawing");
vkCmdBeginRenderingKHR(commandBuffer, dynamicRenderingInfo);

vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout, 0, stack.longs(descriptorSet), null
);
vkCmdBindVertexBuffers(
commandBuffer, 0,
stack.longs(vertexBuffer.vkBuffer()), stack.longs(0)
);

var hostMatrixBuffer = memFloatBuffer(matrixBuffer.hostAddress(), 2 * 16);
cameraMatrix[0].get(0, hostMatrixBuffer);
cameraMatrix[1].get(16, hostMatrixBuffer);

vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkCmdEndRenderingKHR(commandBuffer);
commands.end();

Expand Down Expand Up @@ -309,10 +482,17 @@ public static void main(String[] args) throws InterruptedException {

vkDestroyFence(boiler.vkDevice(), fence, null);
vkDestroyCommandPool(boiler.vkDevice(), commandPool, null);
vkDestroyPipeline(boiler.vkDevice(), graphicsPipeline, null);
vkDestroyPipelineLayout(boiler.vkDevice(), pipelineLayout, null);
vkDestroyDescriptorPool(boiler.vkDevice(), descriptorPool, null);
vkDestroyDescriptorSetLayout(boiler.vkDevice(), descriptorSetLayout, null);
for (long imageView : swapchainImageViews) {
vkDestroyImageView(boiler.vkDevice(), imageView, null);
}

vertexBuffer.destroy(boiler.vmaAllocator());
matrixBuffer.destroy(boiler.vmaAllocator());

xrDestroySpace(renderSpace);
xrDestroySwapchain(swapchain);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#version 450

#extension GL_EXT_multiview : require

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;

layout(location = 0) out vec3 outColor;

layout(binding = 0) uniform Matrices {
mat4 eyes[2];
} matrices;

void main() {
gl_Position = matrices.eyes[gl_ViewIndex] * vec4(inPosition, 1.0);
outColor = inColor;
}
Binary file not shown.

0 comments on commit a1e4ba1

Please sign in to comment.