lunarg 11

This commit is contained in:
Hane 2024-11-09 22:26:03 +01:00
commit 9477f64d50
4 changed files with 460 additions and 4 deletions

View file

@ -1,4 +1,9 @@
REM cd build 2>NUL && cd .. || mkdir build
if not exist build\ mkdir build || goto :EOF
clang++ src/main.cpp -o build/window.exe -O0 -g -gcodeview -lgdi32 -lvulkan-1 -I%VULKAN_SDK%/Include -L%VULKAN_SDK%/Lib -Wl,-pdb=
REM clang++ src/main.cpp -o build/window.exe -O0 -g -gcodeview -stdlib=libc++ -lunwind -lgdi32 -lkernel32 -lvulkan-1 -lSPIRV -lSPIRV-Tools -lSPIRV-Tools-diff -lSPIRV-Tools-opt -lSPVRemapper -lglslang -lOSDependent -lGenericCodeGen -lMachineIndependent -lglslang-default-resource-limits -I%VULKAN_SDK%/Include -L%VULKAN_SDK%/Lib -Wl,-pdb= -v
set VSCMD_SKIP_SENDTELEMETRY=1
set VCPKG_KEEP_ENV_VARS=VSCMD_SKIP_SENDTELEMETRY
vcvarsall.bat x64 && cl.exe /Fe:build\window.exe /std:c++20 /Od /MDd /EHsc -I%VULKAN_SDK%/Include src/main.cpp user32.lib gdi32.lib kernel32.lib vulkan-1.lib SPIRV.lib SPIRV-Toolsd.lib SPIRV-Tools-diffd.lib SPIRV-Tools-optd.lib SPVRemapperd.lib glslangd.lib OSDependentd.lib GenericCodeGend.lib MachineIndependentd.lib glslang-default-resource-limitsd.lib /link /DEBUG:FULL /IGNORE:4099 /LIBPATH:%VULKAN_SDK%/Lib

View file

@ -7,19 +7,43 @@
#define VK_USE_PLATFORM_WAYLAND_KHR
#endif
#define GL_KHR_vulkan_glsl
/* Number of descriptor sets needs to be the same at alloc, */
/* pipeline layout creation, and descriptor set layout creation */
#define NUM_DESCRIPTOR_SETS 1
/* Number of samples needs to be the same at image creation, */
/* renderpass creation and pipeline creation. */
#define NUM_SAMPLES VK_SAMPLE_COUNT_1_BIT
/* Number of viewports and number of scissors have to be the same */
/* at pipeline creation and in any call to set them dynamically */
/* They also have to be the same as each other */
#define NUM_VIEWPORTS 1
#define NUM_SCISSORS NUM_VIEWPORTS
#include <excpt.h>
//#include <eh.h>
#include <cstdint>
#include <cstdio>
#include <cassert>
#include <cwchar>
#include <vector>
#include <exception>
#include <vulkan/vulkan.h>
#include <glm/glm.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glslang/Include/glslang_c_interface.h>
#include <glslang/Public/resource_limits_c.h>
#include <Windows.h>
#include <winuser.h>
#include <wingdi.h>
#include <fileapi.h>
#include <libloaderapi.h>
//LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
typedef struct StateInfo {
@ -503,7 +527,6 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n
memoryAllocInfo.allocationSize = memoryRequirements.size;
uint32_t memoryTypeIndex = 0;
VkFlags requirements = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
// Search memtypes to find first index with those properties
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
@ -516,12 +539,12 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n
memoryRequirements.memoryTypeBits >>= 1;
}
// No memory types matched, return failure
assert(memoryTypeIndex && "No mappable, coherent memory");
assert(memoryAllocInfo.memoryTypeIndex && "No mappable, coherent memory");
result = vkAllocateMemory(device, &memoryAllocInfo, NULL, &(uniformData.mem));
assert(result == VK_SUCCESS);
uint8_t* pData; //VK_WHOLE_SIZE
uint8_t* pData; //VK_WHOLE_SIZE = through buffer end
result = vkMapMemory(device, uniformData.mem, 0, memoryRequirements.size, 0, (void **)&pData);
assert(result == VK_SUCCESS);
@ -532,10 +555,401 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n
result = vkBindBufferMemory(device, uniformData.buf, uniformData.mem, 0);
assert(result == VK_SUCCESS);
/*
* typedef struct VkDescriptorBufferInfo {
* VkBuffer buffer;
* VkDeviceSize offset;
* VkDeviceSize range;
* } VkDescriptorBufferInfo;
*/
uniformData.descriptorBufferInfo.buffer = uniformData.buf;
uniformData.descriptorBufferInfo.offset = 0;
uniformData.descriptorBufferInfo.range = sizeof(MVP);
/* Descriptor set declaration */
/* Start with just our uniform buffer that has our transformation matrices
* (for the vertex shader). The fragment shader we intend to use needs no
* external resources, so nothing else is necessary
*/
/* Note that when we start using textures, this is where our sampler will
* need to be specified
*/
VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {};
descriptorSetLayoutBinding.binding = 0;
descriptorSetLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorSetLayoutBinding.descriptorCount = 1;
descriptorSetLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
descriptorSetLayoutBinding.pImmutableSamplers = NULL;
/* Next take layout bindings and use them to create a descriptor set layout
*/
std::vector<VkDescriptorSetLayout> descriptorSetLayouts;
VkDescriptorSetLayoutCreateInfo descriptorSetInfo = {};
descriptorSetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptorSetInfo.pNext = NULL;
descriptorSetInfo.bindingCount = 1;
descriptorSetInfo.pBindings = &descriptorSetLayoutBinding;
descriptorSetLayouts.resize(NUM_DESCRIPTOR_SETS);
result = vkCreateDescriptorSetLayout(device, &descriptorSetInfo, NULL, descriptorSetLayouts.data());
assert(result == VK_SUCCESS);
/* Now use the descriptor layout to create a pipeline layout */
//Constant ranges constant to shader not used here
VkPipelineLayout pipelineLayout;
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.pNext = NULL;
pipelineLayoutInfo.pushConstantRangeCount = 0;
pipelineLayoutInfo.pPushConstantRanges = NULL;
pipelineLayoutInfo.setLayoutCount = NUM_DESCRIPTOR_SETS;
pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts.data();
result = vkCreatePipelineLayout(device, &pipelineLayoutInfo, NULL, &pipelineLayout);
assert(result == VK_SUCCESS);
/* Descriptor set initialization */
VkDescriptorPoolSize typeCount[1];
typeCount[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
typeCount[0].descriptorCount = 1;
VkDescriptorPool descriptorPool;
VkDescriptorPoolCreateInfo descriptorPoolInfo = {};
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.pNext = NULL;
descriptorPoolInfo.maxSets = 1;
descriptorPoolInfo.poolSizeCount = 1;
descriptorPoolInfo.pPoolSizes = typeCount;
result = vkCreateDescriptorPool(device, &descriptorPoolInfo, NULL, &descriptorPool);
assert(result == VK_SUCCESS);
std::vector<VkDescriptorSet> descriptorSets;
VkDescriptorSetAllocateInfo descriptorSetAllocInfo[1];
descriptorSetAllocInfo[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
descriptorSetAllocInfo[0].pNext = NULL;
descriptorSetAllocInfo[0].descriptorPool = descriptorPool;
descriptorSetAllocInfo[0].descriptorSetCount = NUM_DESCRIPTOR_SETS;
descriptorSetAllocInfo[0].pSetLayouts = descriptorSetLayouts.data();
descriptorSets.resize(NUM_DESCRIPTOR_SETS);
result = vkAllocateDescriptorSets(device, descriptorSetAllocInfo, descriptorSets.data());
assert(result == VK_SUCCESS);
VkWriteDescriptorSet writes[1];
writes[0] = {};
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[0].pNext = NULL;
writes[0].dstSet = descriptorSets[0];
writes[0].descriptorCount = 1;
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
writes[0].pBufferInfo = &uniformData.descriptorBufferInfo;
writes[0].dstArrayElement = 0;
writes[0].dstBinding = 0;
vkUpdateDescriptorSets(device, 1, writes, 0, NULL);
/* Render pass definition */
// A semaphore (or fence) is required in order to acquire a
// swapchain image to prepare it for use in a render pass.
// The semaphore is normally used to hold back the rendering
// operation until the image is actually available.
// But since this sample does not render, the semaphore
// ends up being unused.
VkSemaphore imageAcquiredSemaphore;
VkSemaphoreCreateInfo imageAcquiredSemaphoreInfo;
imageAcquiredSemaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
imageAcquiredSemaphoreInfo.pNext = NULL;
imageAcquiredSemaphoreInfo.flags = 0;
result = vkCreateSemaphore(device, &imageAcquiredSemaphoreInfo, NULL, &imageAcquiredSemaphore);
assert(result == VK_SUCCESS);
// Acquire the swapchain image in order to set its layout
uint32_t currentBuffer;
result = vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE,
&currentBuffer);
assert(result >= 0);
// The initial layout for the color and depth attachments will be
// LAYOUT_UNDEFINED because at the start of the renderpass, we don't
// care about their contents. At the start of the subpass, the color
// attachment's layout will be transitioned to LAYOUT_COLOR_ATTACHMENT_OPTIMAL
// and the depth stencil attachment's layout will be transitioned to
// LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL. At the end of the renderpass,
// the color attachment's layout will be transitioned to
// LAYOUT_PRESENT_SRC_KHR to be ready to present. This is all done as part
// of the renderpass, no barriers are necessary.
VkAttachmentDescription attachments[1];
attachments[0].format = format;
attachments[0].samples = NUM_SAMPLES;
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
attachments[0].flags = 0;
// Depth
/*
* attachments[1].format = info.depth.format;
* attachments[1].samples = NUM_SAMPLES;
* attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
* attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
* attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
* attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
* attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
* attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
* attachments[1].flags = 0;
*/
VkAttachmentReference color_reference = {};
color_reference.attachment = 0;
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
/*
* VkAttachmentReference depth_reference = {};
* depth_reference.attachment = 1;
* depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
*/
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.flags = 0;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = NULL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_reference;
subpass.pResolveAttachments = NULL;
subpass.pDepthStencilAttachment = NULL;//&depth_reference;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = NULL;
// Subpass dependency to wait for wsi image acquired semaphore before starting layout transition
VkSubpassDependency subpassDependency = {};
subpassDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
subpassDependency.dstSubpass = 0;
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpassDependency.srcAccessMask = 0;
subpassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpassDependency.dependencyFlags = 0;
VkRenderPass renderPass;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.pNext = NULL;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = attachments;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &subpassDependency;
result = vkCreateRenderPass(device, &renderPassInfo, NULL, &renderPass);
assert(result == VK_SUCCESS);
/* Shader assignment and creation */
//Creation via runtime GLSL compiling
VkShaderModule vertexShader; //<- spirv bytecode
VkShaderModule fragmentShader;
HANDLE glslFile = CreateFileW(
L"../src/shaderv.vert",
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
//FILE* glslFile = fopen(, "r");
assert(glslFile);
const uint64_t SOURCE_SIZE = 1024 * 1024;
char* source = (char*)calloc(SOURCE_SIZE, sizeof(char));
DWORD bytesRead = 0;
if (!ReadFile(glslFile, source, SOURCE_SIZE, &bytesRead, NULL)) exit(-5);
//char bytesReadString[(6* sizeof(char))];
//itoa(bytesRead, bytesReadString, 10);
//OutputDebugStringA(bytesReadString);
OutputDebugStringA("\n");
glslang_initialize_process();
glslang_stage_t stage = GLSLANG_STAGE_VERTEX;
glslang_input_t input = {
.language = GLSLANG_SOURCE_GLSL,
.stage = stage,
.client = GLSLANG_CLIENT_VULKAN,
.client_version = GLSLANG_TARGET_VULKAN_1_1,
.target_language = GLSLANG_TARGET_SPV,
.target_language_version = GLSLANG_TARGET_SPV_1_3,
.code = source,
.default_version = 100,
.default_profile = GLSLANG_NO_PROFILE,
.force_default_version_and_profile = false,
.forward_compatible = false,
.messages = GLSLANG_MSG_DEFAULT_BIT,
.resource = glslang_default_resource()
};
glslang_shader_t* shader = glslang_shader_create(&input);
OutputDebugStringA("GLSL parse faild\n");
if (!glslang_shader_preprocess(shader, &input)) {
OutputDebugStringA("GLSL preprocessing fail\n");
OutputDebugStringA(glslang_shader_get_info_log(shader));
OutputDebugStringA("\n");
OutputDebugStringA(glslang_shader_get_info_debug_log(shader));
OutputDebugStringA("\n");
OutputDebugStringA(glslang_shader_get_preprocessed_code(shader));
OutputDebugStringA("\n");
exit(-6);
}
if (!glslang_shader_parse(shader, &input)) {
OutputDebugStringA("GLSL parse fail\n");
OutputDebugStringA(glslang_shader_get_info_log(shader));
OutputDebugStringA(glslang_shader_get_info_debug_log(shader));
OutputDebugStringA("\n");
OutputDebugStringA(input.code);
exit(-7);
}
glslang_program_t* program = glslang_program_create();
glslang_program_add_shader(program, shader);
if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) {
exit(-8);
}
glslang_program_SPIRV_generate(program, stage);
std::vector<uint32_t> spirv;
size_t programSize = glslang_program_SPIRV_get_size(program);
spirv.resize(programSize);
glslang_program_SPIRV_get(program, spirv.data());
/*
* const char* spirv_messages = glslang_program_SPIRV_get_messages(program);
* if(spirv_messages) {
* fprintf(stderr, "SPIRV mes: '%s'", spirv_messages);
* }
*/
VkShaderModuleCreateInfo shaderInfo = {};
shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shaderInfo.codeSize = spirv.size() * sizeof(uint32_t);
shaderInfo.pCode = (const uint32_t*)spirv.data();
result = vkCreateShaderModule(device, &shaderInfo, NULL, &vertexShader);
assert(result == VK_SUCCESS);
glslang_program_delete(program);
glslang_shader_delete(shader);
glslang_finalize_process();
//also compile fragment shader
CloseHandle(glslFile);
glslFile = CreateFileW(
L"../src/shaderf.frag",
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
assert(glslFile);
memset(source, 0, SOURCE_SIZE * sizeof(char));
if (!ReadFile(glslFile, source, SOURCE_SIZE, &bytesRead, NULL)) exit(-5);
glslang_initialize_process();
stage = GLSLANG_STAGE_FRAGMENT;
input.stage = stage;
shader = glslang_shader_create(&input);
if (!glslang_shader_preprocess(shader, &input)) {
OutputDebugStringA("GLSL preprocessing fail\n");
OutputDebugStringA(glslang_shader_get_info_log(shader));
OutputDebugStringA("\n");
OutputDebugStringA(glslang_shader_get_info_debug_log(shader));
OutputDebugStringA("\n");
OutputDebugStringA(glslang_shader_get_preprocessed_code(shader));
OutputDebugStringA("\n");
exit(-6);
}
if (!glslang_shader_parse(shader, &input)) {
OutputDebugStringA("GLSL parse fail\n");
OutputDebugStringA(glslang_shader_get_info_log(shader));
OutputDebugStringA(glslang_shader_get_info_debug_log(shader));
OutputDebugStringA("\n");
OutputDebugStringA(input.code);
exit(-7);
};
program = glslang_program_create();
glslang_program_add_shader(program, shader);
if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) {
exit(-8);
}
glslang_program_SPIRV_generate(program, stage);
programSize = glslang_program_SPIRV_get_size(program);
spirv.resize(programSize);
glslang_program_SPIRV_get(program, spirv.data());
/*
* const char* spirv_messages = glslang_program_SPIRV_get_messages(program);
* if(spirv_messages) {
* fprintf(stderr, "SPIRV mes: '%s'", spirv_messages);
* }
*/
shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shaderInfo.codeSize = spirv.size() * sizeof(uint32_t);
shaderInfo.pCode = (const uint32_t*)spirv.data();
result = vkCreateShaderModule(device, &shaderInfo, NULL, &fragmentShader);
assert(result == VK_SUCCESS);
glslang_program_delete(program);
glslang_shader_delete(shader);
glslang_finalize_process();
CloseHandle(glslFile);
free(source);
//Pipeline setup
VkPipelineShaderStageCreateInfo shaderStages[2];
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].pNext = NULL;
shaderStages[0].pSpecializationInfo = NULL;
shaderStages[0].flags = 0;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].pName = "main";
shaderStages[0].module = vertexShader;
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].pNext = NULL;
shaderStages[1].pSpecializationInfo = NULL;
shaderStages[1].flags = 0;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].pName = "main";
shaderStages[1].module = fragmentShader;
//Window show and event loop
@ -548,6 +962,13 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n
DispatchMessage(&msg);
}
vkDestroyShaderModule(device, shaderStages[0].module, NULL);
vkDestroyShaderModule(device, shaderStages[1].module, NULL);
vkDestroyRenderPass(device, renderPass, NULL);
vkDestroySemaphore(device, imageAcquiredSemaphore, NULL);
vkDestroyDescriptorPool(device, descriptorPool, NULL);
for (int i = 0; i < NUM_DESCRIPTOR_SETS; i++) vkDestroyDescriptorSetLayout(device, descriptorSetLayouts[i], NULL);
vkDestroyPipelineLayout(device, pipelineLayout, NULL);
vkDestroyBuffer(device, uniformData.buf, NULL);
vkFreeMemory(device, uniformData.mem, NULL);
VkCommandBuffer cmdBufs[1] = {cmd};

11
src/shaderf.frag Normal file
View file

@ -0,0 +1,11 @@
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (binding = 1) uniform sampler2D tex;
layout (location = 0) in vec2 texcoord;
layout (location = 0) out vec4 outColor;
void main() {
outColor = textureLod(tex, texcoord, 0.0);
}

19
src/shaderv.vert Normal file
View file

@ -0,0 +1,19 @@
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
//set = desc set layout
//binding = desc set binding
//var[I] = descriptor set pos in array
layout (std140, set = 0, binding = 0) uniform buf {
mat4 mvp;
} ubuf;
layout (location = 0) in vec4 pos;
layout (location = 1) in vec2 inTexCoords;
layout (location = 0) out vec2 texcoord;
void main() {
texcoord = inTexCoords;
gl_Position = ubuf.mvp * pos;
}