initial
This commit is contained in:
commit
a978c8a9e6
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.gdb_history
|
||||
*.spv
|
||||
*.o
|
||||
main
|
||||
86
Makefile
Normal file
86
Makefile
Normal file
@ -0,0 +1,86 @@
|
||||
CC=$(PREFIX)gcc
|
||||
CXX=$(PREFIX)g++
|
||||
OBJCOPY=$(PREFIX)objcopy
|
||||
|
||||
OBJARCH = elf64-x86-64
|
||||
|
||||
OPT = -O0 -march=x86-64-v3
|
||||
|
||||
DEBUG = -g
|
||||
|
||||
CSTD = -std=gnu23
|
||||
CXXSTD = -std=gnu++23
|
||||
CFLAGS += -Wall -Werror
|
||||
CFLAGS += -Wfatal-errors
|
||||
CFLAGS += -Wno-error=unused-variable -Wno-error=unused-but-set-variable
|
||||
CFLAGS += -Wno-error=unused-function
|
||||
CFLAGS += -Wno-error=array-bounds
|
||||
CFLAGS += -Wno-unknown-pragmas
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -I./include
|
||||
CFLAGS += -I../SDL3-dist/include
|
||||
CFLAGS += -I../volk
|
||||
CFLAGS += -fpic
|
||||
|
||||
FLAGS += -fstack-protector -fstack-protector-all -fno-omit-frame-pointer -fsanitize=address
|
||||
|
||||
LDFLAGS += -lm
|
||||
ifeq ($(shell uname),Linux)
|
||||
LDFLAGS += -Wl,-z noexecstack
|
||||
endif
|
||||
|
||||
OBJS = \
|
||||
src/main.o
|
||||
|
||||
BINS = \
|
||||
index.idx.o \
|
||||
position_normal_texture.vtx.o
|
||||
|
||||
SHADERS = \
|
||||
shader/triangle.vs.spv.o \
|
||||
shader/triangle.ps.spv.o
|
||||
|
||||
LIBS = \
|
||||
../SDL3-dist/lib64/libSDL3.a \
|
||||
../volk/volk.o
|
||||
|
||||
all: main
|
||||
|
||||
define BUILD_BINARY_O
|
||||
$(OBJCOPY) -I binary -O $(OBJARCH) $< $@
|
||||
endef
|
||||
|
||||
%.vtx.o: %.vtx
|
||||
$(BUILD_BINARY_O)
|
||||
|
||||
%.idx.o: %.idx
|
||||
$(BUILD_BINARY_O)
|
||||
|
||||
%.spv.o: %.spv
|
||||
$(BUILD_BINARY_O)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
||||
|
||||
main: $(OBJS) $(LIBS) $(BINS) $(SHADERS)
|
||||
$(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
|
||||
|
||||
%.vs.spv: %.hlsl
|
||||
../dxc/bin/dxc -spirv -T vs_6_1 -E VSMain -fspv-target-env=vulkan1.3 $< -Fo $@
|
||||
|
||||
%.ps.spv: %.hlsl
|
||||
../dxc/bin/dxc -spirv -T ps_6_1 -E PSMain -fspv-target-env=vulkan1.3 $< -Fo $@
|
||||
|
||||
.SUFFIXES:
|
||||
.INTERMEDIATE:
|
||||
.SECONDARY:
|
||||
.PHONY: all clean phony dist
|
||||
|
||||
%: RCS/%,v
|
||||
%: RCS/%
|
||||
%: %,v
|
||||
%: s.%
|
||||
%: SCCS/s.%
|
||||
2231
include/directxmath/directxmath.h
Normal file
2231
include/directxmath/directxmath.h
Normal file
File diff suppressed because it is too large
Load Diff
2201
include/directxmath/directxmathconvert.inl
Normal file
2201
include/directxmath/directxmathconvert.inl
Normal file
File diff suppressed because it is too large
Load Diff
3554
include/directxmath/directxmathmatrix.inl
Normal file
3554
include/directxmath/directxmathmatrix.inl
Normal file
File diff suppressed because it is too large
Load Diff
2492
include/directxmath/directxmathmisc.inl
Normal file
2492
include/directxmath/directxmathmisc.inl
Normal file
File diff suppressed because it is too large
Load Diff
14869
include/directxmath/directxmathvector.inl
Normal file
14869
include/directxmath/directxmathvector.inl
Normal file
File diff suppressed because it is too large
Load Diff
42
include/new.h
Normal file
42
include/new.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __aligned_alloc
|
||||
#undef __aligned_alloc
|
||||
#endif
|
||||
#ifdef __alloca
|
||||
#undef __alloca
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#define __aligned_alloc(alignment, size) _aligned_malloc(size, alignment)
|
||||
#define __alloca(size) _malloca(size)
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define __aligned_alloc(alignment, size) aligned_alloc(alignment, size)
|
||||
#define __alloca(size) alloca(size)
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
T * New(int elements)
|
||||
{
|
||||
return (T *)__aligned_alloc(16, (sizeof (T)) * elements);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T * NewM(int elements)
|
||||
{
|
||||
return (T *)malloc((sizeof (T)) * elements);
|
||||
}
|
||||
|
||||
/*
|
||||
template <typename T>
|
||||
T * NewA(int elements)
|
||||
{
|
||||
return (T *)__alloca((sizeof (T)) * elements);
|
||||
}
|
||||
*/
|
||||
|
||||
#undef __alloca
|
||||
#undef __aligned_alloc
|
||||
2941
include/sal.h
Normal file
2941
include/sal.h
Normal file
File diff suppressed because it is too large
Load Diff
BIN
position_normal_texture.vtx
Normal file
BIN
position_normal_texture.vtx
Normal file
Binary file not shown.
24
shader/triangle.hlsl
Normal file
24
shader/triangle.hlsl
Normal file
@ -0,0 +1,24 @@
|
||||
static const float2 positions[3] = {
|
||||
float2(0.0, -0.5),
|
||||
float2(0.5, 0.5),
|
||||
float2(-0.5, 0.5)
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Pos : SV_POSITION;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput VSMain(uint VertexIndex: SV_VertexID)
|
||||
{
|
||||
VSOutput output = (VSOutput)0;
|
||||
output.Pos = float4(positions[VertexIndex], 0.0, 1.0);
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 PSMain() : SV_TARGET
|
||||
{
|
||||
return float4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
850
src/main.cpp
Normal file
850
src/main.cpp
Normal file
@ -0,0 +1,850 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "volk.h"
|
||||
#include "vulkan/vk_enum_string_helper.h"
|
||||
#include "SDL3/SDL.h"
|
||||
#include "SDL3/SDL_vulkan.h"
|
||||
#include "directxmath/directxmath.h"
|
||||
|
||||
#include "new.h"
|
||||
|
||||
extern "C" {
|
||||
extern uint8_t const _binary_position_normal_texture_vtx_start[];
|
||||
extern void * const _binary_position_normal_texture_vtx_size;
|
||||
extern uint8_t const _binary_index_idx_start[];
|
||||
extern void * const _binary_index_idx_size;
|
||||
|
||||
extern uint8_t const _binary_shader_triangle_vs_spv_start[];
|
||||
extern void * const _binary_shader_triangle_vs_spv_size;
|
||||
extern uint8_t const _binary_shader_triangle_ps_spv_start[];
|
||||
extern void * const _binary_shader_triangle_ps_spv_size;
|
||||
}
|
||||
|
||||
#define vtx_start _binary_position_normal_texture_vtx_start
|
||||
#define vtx_size (size_t)(&_binary_position_normal_texture_vtx_size)
|
||||
#define idx_start _binary_index_idx_start
|
||||
#define idx_size (size_t)(&_binary_index_idx_size)
|
||||
|
||||
#define vs_start _binary_shader_triangle_vs_spv_start
|
||||
#define vs_size (size_t)(&_binary_shader_triangle_vs_spv_size)
|
||||
#define ps_start _binary_shader_triangle_ps_spv_start
|
||||
#define ps_size (size_t)(&_binary_shader_triangle_ps_spv_size)
|
||||
|
||||
#define SDL_CHECK(f) \
|
||||
{ \
|
||||
bool result = (f); \
|
||||
if (result != true) { \
|
||||
fprintf(stderr, "SDL: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, SDL_GetError()); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SDL_CHECK_NONNULL(f) \
|
||||
{ \
|
||||
void * ptr = (void *)(f); \
|
||||
if (ptr == nullptr) { \
|
||||
fprintf(stderr, "SDL: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, SDL_GetError()); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VK_CHECK(f) \
|
||||
{ \
|
||||
VkResult result = (f); \
|
||||
if (result != VK_SUCCESS) { \
|
||||
fprintf(stderr, "VK: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, string_VkResult(result)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VK_CHECK_SWAPCHAIN(f) \
|
||||
{ \
|
||||
VkResult result = (f); \
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) { \
|
||||
updateSwapchain = true; \
|
||||
} else if (result != VK_SUCCESS) { \
|
||||
fprintf(stderr, "VK: %s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, string_VkResult(result)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASSERT(expr, msg) \
|
||||
{ \
|
||||
bool result = (expr); \
|
||||
if (result != true) { \
|
||||
fprintf(stderr, "%s %s L%d error: `%s`\n", __FILE__, __func__, __LINE__, msg); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
|
||||
#define UNREACHABLE() __assume(false);
|
||||
#else // GCC, Clang
|
||||
#define UNREACHABLE() __builtin_unreachable();
|
||||
#endif
|
||||
|
||||
constexpr uint32_t maxFramesInFlight{ 2 };
|
||||
|
||||
VkInstance instance{ VK_NULL_HANDLE };
|
||||
VkDevice device{ VK_NULL_HANDLE };
|
||||
VkQueue queue{ VK_NULL_HANDLE };
|
||||
VkSurfaceKHR surface{ VK_NULL_HANDLE };
|
||||
VkSwapchainKHR swapchain{ VK_NULL_HANDLE };
|
||||
|
||||
VkImage * swapchainImages{ nullptr };
|
||||
VkImageView * swapchainImageViews{ nullptr };
|
||||
|
||||
VkImage depthImage{ VK_NULL_HANDLE };
|
||||
VkImageView depthImageView{ VK_NULL_HANDLE };
|
||||
|
||||
VkBuffer vertexIndexBuffer{ VK_NULL_HANDLE };
|
||||
|
||||
VkFence fences[maxFramesInFlight];
|
||||
VkSemaphore presentSemaphores[maxFramesInFlight];
|
||||
VkSemaphore * renderSemaphores{ nullptr };
|
||||
|
||||
VkCommandPool commandPool{ VK_NULL_HANDLE };
|
||||
VkCommandBuffer commandBuffers[maxFramesInFlight];
|
||||
|
||||
VkPipeline pipeline{ VK_NULL_HANDLE };
|
||||
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
|
||||
|
||||
XMINT2 windowSize{};
|
||||
|
||||
struct ShaderData {
|
||||
XMFLOAT4X4 projection;
|
||||
XMFLOAT4X4 view;
|
||||
XMFLOAT4X4 model[3];
|
||||
XMFLOAT4 lightPos{ 0.0f, -10.0f, 10.0f, 0.0f };
|
||||
uint32_t selected{ 1 };
|
||||
} shaderData{};
|
||||
|
||||
struct ShaderDataBuffer {
|
||||
VkBuffer buffer{ VK_NULL_HANDLE };
|
||||
VkDeviceAddress deviceAddress{};
|
||||
};
|
||||
|
||||
ShaderDataBuffer shaderDataBuffers[maxFramesInFlight];
|
||||
|
||||
static void print_memoryPropertyFlags(VkMemoryPropertyFlags propertyFlags)
|
||||
{
|
||||
int index = 0;
|
||||
while (propertyFlags) {
|
||||
if (propertyFlags & 1) {
|
||||
if (index != 0)
|
||||
printf("|");
|
||||
printf(string_VkMemoryPropertyFlagBits((VkMemoryPropertyFlagBits)(1u << index)));
|
||||
}
|
||||
propertyFlags >>= 1;
|
||||
index += 1;
|
||||
};
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
uint32_t findMemoryTypeIndex(VkPhysicalDeviceMemoryProperties const * memoryProperties, uint32_t memoryTypeBits, VkMemoryPropertyFlags propertyFlags)
|
||||
{
|
||||
for (uint32_t i = 0; i < memoryProperties->memoryTypeCount; i++) {
|
||||
if (!(memoryTypeBits & (1u << i)))
|
||||
continue;
|
||||
|
||||
if (memoryProperties->memoryTypes[i].propertyFlags == propertyFlags) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
ASSERT(false, "no memory type index matching memoryTypeBits and propertyFlags");
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
SDL_CHECK(SDL_Init(SDL_INIT_VIDEO));
|
||||
SDL_CHECK(SDL_Vulkan_LoadLibrary(NULL));
|
||||
volkInitialize();
|
||||
|
||||
VkApplicationInfo appInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pApplicationName = "Vulkan",
|
||||
.apiVersion = VK_API_VERSION_1_3
|
||||
};
|
||||
|
||||
uint32_t instanceExtensionsCount{ 0 };
|
||||
char const * const * instanceExtensions{ SDL_Vulkan_GetInstanceExtensions(&instanceExtensionsCount) };
|
||||
|
||||
VkInstanceCreateInfo instanceCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pApplicationInfo = &appInfo,
|
||||
.enabledExtensionCount = instanceExtensionsCount,
|
||||
.ppEnabledExtensionNames = instanceExtensions,
|
||||
};
|
||||
VK_CHECK(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
|
||||
|
||||
volkLoadInstance(instance);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// physical device and queue family index
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint32_t physicalDeviceCount{ 0 };
|
||||
VK_CHECK(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
|
||||
VkPhysicalDevice * physicalDevices = NewM<VkPhysicalDevice>(physicalDeviceCount);
|
||||
VK_CHECK(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices));
|
||||
|
||||
uint32_t physicalDeviceIndex{ 0 };
|
||||
printf("physicalDeviceCount %d\n", physicalDeviceCount);
|
||||
for (uint32_t i = 0; i < physicalDeviceCount; i++) {
|
||||
VkPhysicalDeviceProperties2 properties{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 };
|
||||
vkGetPhysicalDeviceProperties2(physicalDevices[i], &properties);
|
||||
printf("devices[%d] name: %s%s\n", i, properties.properties.deviceName, (i == physicalDeviceIndex) ? " [selected]" : "");
|
||||
if (i == physicalDeviceIndex) {
|
||||
printf("limits:\n");
|
||||
printf(" maxImageDimension1D %u\n", properties.properties.limits.maxImageDimension1D);
|
||||
printf(" maxImageDimension2D %u\n", properties.properties.limits.maxImageDimension2D);
|
||||
printf(" maxMemoryAllocationCount %u\n", properties.properties.limits.maxMemoryAllocationCount);
|
||||
printf(" maxSamplerAllocationCount %u\n", properties.properties.limits.maxSamplerAllocationCount);
|
||||
}
|
||||
}
|
||||
VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex];
|
||||
free(physicalDevices);
|
||||
|
||||
uint32_t queueFamilyCount{ 0 };
|
||||
vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyCount, nullptr);
|
||||
VkQueueFamilyProperties2 * queueFamilyProperties = NewM<VkQueueFamilyProperties2>(queueFamilyCount);
|
||||
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
||||
queueFamilyProperties[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
|
||||
queueFamilyProperties[i].pNext = nullptr;
|
||||
}
|
||||
vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyCount, queueFamilyProperties);
|
||||
uint32_t queueFamilyIndex{ ~0u };
|
||||
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
||||
VkQueueFlags queueFlags = queueFamilyProperties[i].queueFamilyProperties.queueFlags;
|
||||
if ((queueFlags & VK_QUEUE_GRAPHICS_BIT) && (queueFlags & VK_QUEUE_COMPUTE_BIT)) {
|
||||
queueFamilyIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(queueFamilyIndex != ~0u, "no queue with VK_QUEUE_GRAPHICS_BIT && VK_QUEUE_COMPUTE_BIT");
|
||||
free(queueFamilyProperties);
|
||||
|
||||
SDL_CHECK(SDL_Vulkan_GetPresentationSupport(instance, physicalDevice, queueFamilyIndex));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// memory
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkPhysicalDeviceMemoryProperties2 memoryProperties{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
|
||||
.pNext = nullptr
|
||||
};
|
||||
vkGetPhysicalDeviceMemoryProperties2(physicalDevice, &memoryProperties);
|
||||
/*
|
||||
for (uint32_t i = 0; i < memoryProperties.memoryProperties.memoryTypeCount; i++) {
|
||||
printf("memoryTypes[%u].propertyFlags: ", i);
|
||||
print_memoryPropertyFlags(memoryProperties.memoryProperties.memoryTypes[i].propertyFlags);
|
||||
printf("memoryTypes[%u].heapIndex: %u\n", i, memoryProperties.memoryProperties.memoryTypes[i].heapIndex);
|
||||
}
|
||||
for (uint32_t i = 0; i < memoryProperties.memoryProperties.memoryHeapCount; i++) {
|
||||
printf("memoryHeaps[%u].size %lu\n", i, memoryProperties.memoryProperties.memoryHeaps[i].size);
|
||||
printf("memoryHeaps[%u].flags %08x\n", i, memoryProperties.memoryProperties.memoryHeaps[i].flags);
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// device and queue
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
const float queuePriorities{ 1.0f };
|
||||
VkDeviceQueueCreateInfo queueCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
.queueFamilyIndex = queueFamilyIndex,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = &queuePriorities
|
||||
};
|
||||
VkPhysicalDeviceVulkan12Features enabledVulkan12Features{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.descriptorIndexing = true,
|
||||
.shaderSampledImageArrayNonUniformIndexing = true,
|
||||
.descriptorBindingVariableDescriptorCount = true,
|
||||
.runtimeDescriptorArray = true,
|
||||
.bufferDeviceAddress = true
|
||||
};
|
||||
VkPhysicalDeviceVulkan13Features enabledVulkan13Features{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
||||
.pNext = &enabledVulkan12Features,
|
||||
.synchronization2 = true,
|
||||
.dynamicRendering = true,
|
||||
};
|
||||
VkPhysicalDeviceFeatures enabledFeatures{
|
||||
.samplerAnisotropy = VK_TRUE
|
||||
};
|
||||
constexpr uint32_t enabledExtensionCount = 1;
|
||||
char const * enabledExtensionNames[enabledExtensionCount]{ VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||
VkDeviceCreateInfo deviceCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = &enabledVulkan13Features,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &queueCreateInfo,
|
||||
.enabledExtensionCount = enabledExtensionCount,
|
||||
.ppEnabledExtensionNames = enabledExtensionNames,
|
||||
.pEnabledFeatures = &enabledFeatures
|
||||
};
|
||||
VK_CHECK(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device));
|
||||
vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// window and surface
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
SDL_Window * window = SDL_CreateWindow("Vulkan", 1024, 1024, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
||||
SDL_CHECK_NONNULL(window);
|
||||
SDL_CHECK(SDL_Vulkan_CreateSurface(window, instance, nullptr, &surface));
|
||||
SDL_CHECK(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y));
|
||||
VkSurfaceCapabilitiesKHR surfaceCapabilities{};
|
||||
VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities));
|
||||
printf("surfaceCapabilities currentExtent %d %d\n", surfaceCapabilities.currentExtent.width, surfaceCapabilities.currentExtent.height);
|
||||
uint32_t surfaceFormatCount{ 0 };
|
||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount, nullptr));
|
||||
VkSurfaceFormatKHR * surfaceFormats = NewM<VkSurfaceFormatKHR>(surfaceFormatCount);
|
||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount, surfaceFormats));
|
||||
uint32_t surfaceFormatIndex{ 0 };
|
||||
printf("surfaceFormatCount %d\n", surfaceFormatCount);
|
||||
for (uint32_t i = 0; i < surfaceFormatCount; i++) {
|
||||
printf("surfaceFormat[%d] %s %s%s\n", i, string_VkFormat(surfaceFormats[i].format), string_VkColorSpaceKHR(surfaceFormats[i].colorSpace), (i == surfaceFormatIndex) ? " [selected]" : "");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// swapchain and images
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkExtent2D imageExtent {
|
||||
.width = surfaceCapabilities.currentExtent.width,
|
||||
.height = surfaceCapabilities.currentExtent.height,
|
||||
};
|
||||
VkFormat imageFormat{ surfaceFormats[surfaceFormatIndex].format };
|
||||
VkColorSpaceKHR imageColorSpace{ surfaceFormats[surfaceFormatIndex].colorSpace };
|
||||
free(surfaceFormats);
|
||||
VkSwapchainCreateInfoKHR swapchainCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.surface = surface,
|
||||
.minImageCount = surfaceCapabilities.minImageCount,
|
||||
.imageFormat = imageFormat,
|
||||
.imageColorSpace = imageColorSpace,
|
||||
.imageExtent = imageExtent,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
|
||||
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||
.presentMode = VK_PRESENT_MODE_FIFO_KHR
|
||||
};
|
||||
VK_CHECK(vkCreateSwapchainKHR(device, &swapchainCreateInfo, nullptr, &swapchain));
|
||||
|
||||
uint32_t swapchainImageCount{ 0 };
|
||||
VK_CHECK(vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, nullptr));
|
||||
swapchainImages = NewM<VkImage>(swapchainImageCount);
|
||||
VK_CHECK(vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages));
|
||||
swapchainImageViews = NewM<VkImageView>(swapchainImageCount);
|
||||
for (uint32_t i = 0; i < swapchainImageCount; i++) {
|
||||
VkImageViewCreateInfo imageViewCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = swapchainImages[i],
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = imageFormat,
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
VK_CHECK(vkCreateImageView(device, &imageViewCreateInfo, nullptr, &swapchainImageViews[i]));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// depth
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkFormat depthFormat{ VK_FORMAT_UNDEFINED };
|
||||
constexpr uint32_t depthFormatCount = 2;
|
||||
VkFormat depthFormatList[depthFormatCount]{ VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
|
||||
for (uint32_t i = 0; i < depthFormatCount; i++) {
|
||||
VkFormatProperties2 formatProperties{ .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 };
|
||||
vkGetPhysicalDeviceFormatProperties2(physicalDevice, depthFormatList[i], &formatProperties);
|
||||
if (formatProperties.formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
depthFormat = depthFormatList[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(depthFormat != VK_FORMAT_UNDEFINED, "no depth format with VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT");
|
||||
printf("depthFormat: %s\n", string_VkFormat(depthFormat));
|
||||
|
||||
VkImageCreateInfo depthImageCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = depthFormat,
|
||||
.extent{
|
||||
.width = imageExtent.width,
|
||||
.height = imageExtent.height,
|
||||
.depth = 1,
|
||||
},
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
|
||||
VK_CHECK(vkCreateImage(device, &depthImageCreateInfo, nullptr, &depthImage));
|
||||
|
||||
VkMemoryRequirements depthImageMemoryRequirements;
|
||||
vkGetImageMemoryRequirements(device, depthImage, &depthImageMemoryRequirements);
|
||||
VkMemoryPropertyFlags depthImageMemoryPropertyFlags{
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
};
|
||||
uint32_t depthImageMemoryTypeIndex = findMemoryTypeIndex(&memoryProperties.memoryProperties, depthImageMemoryRequirements.memoryTypeBits, depthImageMemoryPropertyFlags);
|
||||
VkMemoryAllocateInfo depthImageAllocateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = depthImageMemoryRequirements.size,
|
||||
.memoryTypeIndex = depthImageMemoryTypeIndex,
|
||||
};
|
||||
VkDeviceMemory depthImageMemory;
|
||||
VK_CHECK(vkAllocateMemory(device, &depthImageAllocateInfo, nullptr, &depthImageMemory));
|
||||
VK_CHECK(vkBindImageMemory(device, depthImage, depthImageMemory, 0));
|
||||
|
||||
VkImageViewCreateInfo depthViewCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = depthImage,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = depthFormat,
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
VK_CHECK(vkCreateImageView(device, &depthViewCreateInfo, nullptr, &depthImageView));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// mesh
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkDeviceSize vtxBufferSize{ vtx_size };
|
||||
VkDeviceSize idxBufferSize{ idx_size };
|
||||
VkBufferCreateInfo vertexIndexBufferCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = vtxBufferSize + idxBufferSize,
|
||||
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||
};
|
||||
VK_CHECK(vkCreateBuffer(device, &vertexIndexBufferCreateInfo, nullptr, &vertexIndexBuffer));
|
||||
|
||||
VkMemoryRequirements vertexIndexBufferMemoryRequirements;
|
||||
vkGetBufferMemoryRequirements(device, vertexIndexBuffer, &vertexIndexBufferMemoryRequirements);
|
||||
VkMemoryPropertyFlags vertexIndexBufferMemoryPropertyFlags{
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||
};
|
||||
uint32_t vertexIndexBufferMemoryTypeIndex = findMemoryTypeIndex(&memoryProperties.memoryProperties, vertexIndexBufferMemoryRequirements.memoryTypeBits, vertexIndexBufferMemoryPropertyFlags);
|
||||
VkMemoryAllocateInfo vertexIndexBufferAllocateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = vertexIndexBufferMemoryRequirements.size,
|
||||
.memoryTypeIndex = vertexIndexBufferMemoryTypeIndex,
|
||||
};
|
||||
VkDeviceMemory vertexIndexBufferMemory;
|
||||
VK_CHECK(vkAllocateMemory(device, &vertexIndexBufferAllocateInfo, nullptr, &vertexIndexBufferMemory));
|
||||
VK_CHECK(vkBindBufferMemory(device, vertexIndexBuffer, vertexIndexBufferMemory, 0));
|
||||
|
||||
void * mappedData;
|
||||
VK_CHECK(vkMapMemory(device, vertexIndexBufferMemory, 0, vertexIndexBufferCreateInfo.size, 0, &mappedData));
|
||||
memcpy((void *)(((ptrdiff_t)mappedData) + 0), vtx_start, vtx_size);
|
||||
memcpy((void *)(((ptrdiff_t)mappedData) + vtx_size), idx_start, idx_size);
|
||||
vkUnmapMemory(device, vertexIndexBufferMemory);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// shader buffers
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
for (uint32_t i = 0; i < maxFramesInFlight; i++) {
|
||||
VkBufferCreateInfo shaderBufferCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = sizeof(ShaderData),
|
||||
.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||
};
|
||||
|
||||
VK_CHECK(vkCreateBuffer(device, &shaderBufferCreateInfo, nullptr, &shaderDataBuffers[i].buffer));
|
||||
|
||||
VkMemoryRequirements shaderBufferMemoryRequirements;
|
||||
vkGetBufferMemoryRequirements(device, shaderDataBuffers[i].buffer, &shaderBufferMemoryRequirements);
|
||||
|
||||
VkMemoryPropertyFlags shaderBufferMemoryPropertyFlags{
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||
};
|
||||
uint32_t shaderBufferMemoryTypeIndex = findMemoryTypeIndex(&memoryProperties.memoryProperties, depthImageMemoryRequirements.memoryTypeBits, shaderBufferMemoryPropertyFlags);
|
||||
VkMemoryAllocateFlagsInfo shaderBufferAllocateFlagsInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
|
||||
.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
|
||||
};
|
||||
VkMemoryAllocateInfo shaderBufferAllocateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &shaderBufferAllocateFlagsInfo,
|
||||
.allocationSize = shaderBufferMemoryRequirements.size,
|
||||
.memoryTypeIndex = shaderBufferMemoryTypeIndex,
|
||||
};
|
||||
VkDeviceMemory shaderBufferMemory;
|
||||
VK_CHECK(vkAllocateMemory(device, &shaderBufferAllocateInfo, nullptr, &shaderBufferMemory));
|
||||
VK_CHECK(vkBindBufferMemory(device, shaderDataBuffers[i].buffer, shaderBufferMemory, 0));
|
||||
|
||||
VkBufferDeviceAddressInfo shaderBufferDeviceAddressInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
||||
.buffer = shaderDataBuffers[i].buffer
|
||||
};
|
||||
shaderDataBuffers[i].deviceAddress = vkGetBufferDeviceAddress(device, &shaderBufferDeviceAddressInfo);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// synchronization objects
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
|
||||
};
|
||||
VkFenceCreateInfo fenceCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||
.flags = VK_FENCE_CREATE_SIGNALED_BIT
|
||||
};
|
||||
for (uint32_t i = 0; i < maxFramesInFlight; i++) {
|
||||
VK_CHECK(vkCreateFence(device, &fenceCreateInfo, nullptr, &fences[i]));
|
||||
VK_CHECK(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &presentSemaphores[i]));
|
||||
}
|
||||
renderSemaphores = NewM<VkSemaphore>(swapchainImageCount);
|
||||
for (uint32_t i = 0; i < swapchainImageCount; i++) {
|
||||
VK_CHECK(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderSemaphores[i]));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// command
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkCommandPoolCreateInfo commandPoolCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
.queueFamilyIndex = queueFamilyIndex
|
||||
};
|
||||
VK_CHECK(vkCreateCommandPool(device, &commandPoolCreateInfo, nullptr, &commandPool));
|
||||
|
||||
VkCommandBufferAllocateInfo commandBufferAllocateCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = commandPool,
|
||||
.commandBufferCount = maxFramesInFlight
|
||||
};
|
||||
VK_CHECK(vkAllocateCommandBuffers(device, &commandBufferAllocateCreateInfo, commandBuffers));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// shaders
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkShaderModuleCreateInfo vertexShaderModuleCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = vs_size,
|
||||
.pCode = (uint32_t *)vs_start
|
||||
};
|
||||
VkShaderModule vertexShaderModule{};
|
||||
VK_CHECK(vkCreateShaderModule(device, &vertexShaderModuleCreateInfo, nullptr, &vertexShaderModule));
|
||||
|
||||
VkShaderModuleCreateInfo pixelShaderModuleCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = ps_size,
|
||||
.pCode = (uint32_t *)ps_start
|
||||
};
|
||||
VkShaderModule pixelShaderModule{};
|
||||
VK_CHECK(vkCreateShaderModule(device, &pixelShaderModuleCreateInfo, nullptr, &pixelShaderModule));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// pipeline
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkPushConstantRange pushConstantRange{
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.size = sizeof(VkDeviceAddress)
|
||||
};
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 0,
|
||||
.pSetLayouts = nullptr,
|
||||
//.setLayoutCount = 1,
|
||||
//.pSetLayouts = &descriptorSetLayoutTex,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &pushConstantRange
|
||||
};
|
||||
VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||
|
||||
VkVertexInputBindingDescription vertexBindingDescriptions[1]{
|
||||
{
|
||||
.binding = 0,
|
||||
.stride = (3 * (sizeof (float)) * 3),
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||
}
|
||||
};
|
||||
VkVertexInputAttributeDescription vertexAttributeDescriptions[3]{
|
||||
{ .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 0 },
|
||||
{ .location = 1, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 1 },
|
||||
{ .location = 2, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 2 },
|
||||
};
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 1,
|
||||
.pVertexBindingDescriptions = vertexBindingDescriptions,
|
||||
.vertexAttributeDescriptionCount = 3,
|
||||
.pVertexAttributeDescriptions = vertexAttributeDescriptions,
|
||||
};
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
|
||||
};
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaderStages[2]{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.module = vertexShaderModule, .pName = "VSMain"
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.module = pixelShaderModule, .pName = "PSMain"
|
||||
}
|
||||
};
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1
|
||||
};
|
||||
|
||||
VkDynamicState dynamicStates[2]{
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
};
|
||||
VkPipelineDynamicStateCreateInfo dynamicState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.dynamicStateCount = 2,
|
||||
.pDynamicStates = dynamicStates
|
||||
};
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
.depthTestEnable = VK_TRUE,
|
||||
.depthWriteEnable = VK_TRUE,
|
||||
.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL
|
||||
};
|
||||
|
||||
VkPipelineRenderingCreateInfo renderingCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachmentFormats = &imageFormat,
|
||||
.depthAttachmentFormat = depthFormat
|
||||
};
|
||||
|
||||
VkPipelineColorBlendAttachmentState blendAttachment{
|
||||
.colorWriteMask = 0xF
|
||||
};
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &blendAttachment
|
||||
};
|
||||
VkPipelineRasterizationStateCreateInfo rasterizationState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||
.lineWidth = 1.0f
|
||||
};
|
||||
VkPipelineMultisampleStateCreateInfo multisampleState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
|
||||
};
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = &renderingCreateInfo,
|
||||
.stageCount = 2,
|
||||
.pStages = shaderStages,
|
||||
.pVertexInputState = &vertexInputState,
|
||||
.pInputAssemblyState = &inputAssemblyState,
|
||||
.pViewportState = &viewportState,
|
||||
.pRasterizationState = &rasterizationState,
|
||||
.pMultisampleState = &multisampleState,
|
||||
.pDepthStencilState = &depthStencilState,
|
||||
.pColorBlendState = &colorBlendState,
|
||||
.pDynamicState = &dynamicState,
|
||||
.layout = pipelineLayout
|
||||
};
|
||||
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// loop
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool updateSwapchain{ false };
|
||||
uint32_t frameIndex{ 0 };
|
||||
uint32_t imageIndex{ 0 };
|
||||
bool quit{ false };
|
||||
while (quit == false) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
quit = true;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for fence
|
||||
VK_CHECK(vkWaitForFences(device, 1, &fences[frameIndex], true, UINT64_MAX));
|
||||
VK_CHECK(vkResetFences(device, 1, &fences[frameIndex]));
|
||||
|
||||
// acquire next image
|
||||
VK_CHECK_SWAPCHAIN(vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, presentSemaphores[frameIndex], VK_NULL_HANDLE, &imageIndex));
|
||||
|
||||
// command buffer
|
||||
VkCommandBuffer& commandBuffer = commandBuffers[frameIndex];
|
||||
VK_CHECK(vkResetCommandBuffer(commandBuffer, 0));
|
||||
VkCommandBufferBeginInfo commandBufferBeginInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
};
|
||||
VK_CHECK(vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo));
|
||||
|
||||
VkImageMemoryBarrier2 outputBarriers[2]{
|
||||
VkImageMemoryBarrier2{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
.srcAccessMask = 0,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.image = swapchainImages[imageIndex],
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
},
|
||||
VkImageMemoryBarrier2{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
||||
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
|
||||
.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.image = depthImage,
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
VkDependencyInfo barrierDependencyInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
.imageMemoryBarrierCount = 2,
|
||||
.pImageMemoryBarriers = outputBarriers
|
||||
};
|
||||
vkCmdPipelineBarrier2(commandBuffer, &barrierDependencyInfo);
|
||||
|
||||
VkRenderingAttachmentInfo colorRenderingAttachmentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = swapchainImageViews[imageIndex],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue{ .color{ 0.0f, 0.0f, 0.2f, 1.0f } }
|
||||
};
|
||||
VkRenderingAttachmentInfo depthRenderingAttachmentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = depthImageView,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
.clearValue{ .depthStencil{ 1.0f, 0 } }
|
||||
};
|
||||
|
||||
VkRenderingInfo renderingInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.renderArea{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } },
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &colorRenderingAttachmentInfo,
|
||||
.pDepthAttachment = &depthRenderingAttachmentInfo
|
||||
};
|
||||
vkCmdBeginRendering(commandBuffer, &renderingInfo);
|
||||
|
||||
VkViewport viewport{
|
||||
.width = static_cast<float>(windowSize.x),
|
||||
.height = static_cast<float>(windowSize.y),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f
|
||||
};
|
||||
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||
VkRect2D scissor{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } };
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
VkDeviceSize vertexOffset{ 0 };
|
||||
//vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSetTex, 0, nullptr);
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset);
|
||||
VkDeviceSize indexOffset{ vtxBufferSize };
|
||||
vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VkDeviceAddress), &shaderDataBuffers[frameIndex].deviceAddress);
|
||||
VkDeviceSize indexCount{ 3 };
|
||||
vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
|
||||
vkCmdEndRendering(commandBuffer);
|
||||
|
||||
VkImageMemoryBarrier2 barrierPresent{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
.dstAccessMask = 0,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
.image = swapchainImages[imageIndex],
|
||||
.subresourceRange{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = 1, .layerCount = 1 }
|
||||
};
|
||||
VkDependencyInfo barrierPresentDependencyInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
.imageMemoryBarrierCount = 1,
|
||||
.pImageMemoryBarriers = &barrierPresent
|
||||
};
|
||||
vkCmdPipelineBarrier2(commandBuffer, &barrierPresentDependencyInfo);
|
||||
|
||||
VK_CHECK(vkEndCommandBuffer(commandBuffer));
|
||||
|
||||
// submit to graphics queue
|
||||
VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo submitInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &presentSemaphores[frameIndex],
|
||||
.pWaitDstStageMask = &waitStages,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &commandBuffer,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &renderSemaphores[imageIndex],
|
||||
};
|
||||
VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fences[frameIndex]));
|
||||
|
||||
frameIndex = (frameIndex + 1) % maxFramesInFlight;
|
||||
|
||||
// present
|
||||
VkPresentInfoKHR presentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &renderSemaphores[imageIndex],
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &swapchain,
|
||||
.pImageIndices = &imageIndex
|
||||
};
|
||||
VK_CHECK_SWAPCHAIN(vkQueuePresentKHR(queue, &presentInfo));
|
||||
|
||||
assert(updateSwapchain == 0);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user