From 078b97e48b5ad5fcf3f5a16bb081ea0efb1f931b Mon Sep 17 00:00:00 2001 From: quou Date: Mon, 23 Dec 2024 21:30:13 +1100 Subject: send textures to shaders --- c2.cpp | 23 ++- glad_vk.h | 211 ++++++++++++++++++++++++--- intermediate/triangle.glsl | 19 ++- pipeline.cpp | 18 +++ sc/sc.cpp | 125 +++++++++++++++- video.cpp | 351 +++++++++++++++++++++++++++++++++++++++++++-- video.hpp | 55 +++++++ 7 files changed, 764 insertions(+), 38 deletions(-) diff --git a/c2.cpp b/c2.cpp index af912e5..8ba1772 100644 --- a/c2.cpp +++ b/c2.cpp @@ -11,9 +11,9 @@ extern "C" { #define per_frame_memory_size (1024 * 1024) static float verts[] = { - 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.0f, -0.5f, 0.0f, 0.0f, 1.0f + 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }; struct C2 : public App { @@ -49,6 +49,15 @@ static Buffer_Id upload_verts(Device* dev) { return vbo; } +static Sampler_Id create_clamped_linear(Device* dev) { + Sampler_State s{}; + s.min = Filter_Mode::linear; + s.mag = Filter_Mode::linear; + s.address_u = Address_Mode::repeat; + s.address_v = Address_Mode::repeat; + return dev->create_sampler(s); +} + int main() { Arena video_arena; Arena asset_arena; @@ -57,6 +66,7 @@ int main() { Shader* shader; Texture* texture; Buffer_Id vbo; + Sampler_Id clamped_linear; C2* app = App::create("c2"); void* per_frame; app->running = 1; @@ -79,6 +89,7 @@ int main() { dev->heap, per_frame_memory_size ); + clamped_linear = create_clamped_linear(dev); assert(per_frame != 0); uint8_t r = 0; vbo = upload_verts(dev); @@ -97,6 +108,11 @@ int main() { pb.begin(); pb.shader(shader->id); pb.vertex_format(shader->vf); + pb.texture( + shader->descriptor_index("colour_texture"), + texture->id, + clamped_linear + ); Pipeline& pip = pb.build(); Vertex_Buffer_Binding binding[] = {{ @@ -118,6 +134,7 @@ int main() { app->end(); } assets.destroy(); + dev->destroy_sampler(clamped_linear); dev->destroy_buffer(vbo); dev->destroy(); app->destroy(); diff --git a/glad_vk.h b/glad_vk.h index 88a2e87..0f25c4d 100644 --- a/glad_vk.h +++ b/glad_vk.h @@ -1,11 +1,11 @@ /** - * Loader generated by glad 2.0.4 on Tue Aug 15 10:57:41 2023 + * Loader generated by glad 2.0.8 on Mon Dec 23 05:21:50 2024 * * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 * * Generator: C/C++ * Specification: vk - * Extensions: 5 + * Extensions: 7 * * APIs: * - vulkan=1.0 @@ -19,10 +19,10 @@ * - ON_DEMAND = False * * Commandline: - * --api='vulkan=1.0' --extensions='VK_EXT_debug_utils,VK_KHR_surface,VK_KHR_swapchain,VK_KHR_win32_surface,VK_KHR_xlib_surface' c --header-only --loader + * --api='vulkan=1.0' --extensions='VK_EXT_custom_border_color,VK_EXT_debug_utils,VK_KHR_get_physical_device_properties2,VK_KHR_surface,VK_KHR_swapchain,VK_KHR_win32_surface,VK_KHR_xlib_surface' c --header-only --loader * * Online: - * http://glad.sh/#api=vulkan%3D1.0&extensions=VK_EXT_debug_utils%2CVK_KHR_surface%2CVK_KHR_swapchain%2CVK_KHR_win32_surface%2CVK_KHR_xlib_surface&generator=c&options=HEADER_ONLY%2CLOADER + * http://glad.sh/#api=vulkan%3D1.0&extensions=VK_EXT_custom_border_color%2CVK_EXT_debug_utils%2CVK_KHR_get_physical_device_properties2%2CVK_KHR_surface%2CVK_KHR_swapchain%2CVK_KHR_win32_surface%2CVK_KHR_xlib_surface&generator=c&options=HEADER_ONLY%2CLOADER * */ @@ -152,7 +152,7 @@ extern "C" { #define GLAD_VERSION_MAJOR(version) (version / 10000) #define GLAD_VERSION_MINOR(version) (version % 10000) -#define GLAD_GENERATOR_VERSION "2.0.4" +#define GLAD_GENERATOR_VERSION "2.0.8" typedef void (*GLADapiproc)(void); @@ -165,9 +165,13 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro #endif /* GLAD_PLATFORM_H_ */ #define VK_ATTACHMENT_UNUSED (~0U) +#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" +#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 #define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" #define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 #define VK_FALSE 0 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" #define VK_KHR_SURFACE_SPEC_VERSION 25 #define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" @@ -208,7 +212,7 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro /* File: vk_platform.h */ /* */ /* -** Copyright 2014-2023 The Khronos Group Inc. +** Copyright 2014-2024 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -336,10 +340,10 @@ extern "C" /* Vulkan 1.0 version number */ #define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)/* Patch version should always be set to 0 */ /* Version of this file */ -#define VK_HEADER_VERSION 261 +#define VK_HEADER_VERSION 304 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; #ifndef VK_USE_64_BIT_PTR_DEFINES - #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64) #define VK_USE_64_BIT_PTR_DEFINES 1 #else #define VK_USE_64_BIT_PTR_DEFINES 0 @@ -450,6 +454,8 @@ typedef enum VkBorderColor { VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, + VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, + VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF } VkBorderColor; typedef enum VkPipelineCacheHeaderVersion { @@ -1084,6 +1090,15 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46, VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47, VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008, VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, @@ -1094,11 +1109,23 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012, VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000, VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001, VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT = 1000128002, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004, + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; typedef enum VkSystemAllocationScope { @@ -1272,6 +1299,7 @@ typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugUtilsMessageTypeFlagBitsEXT; typedef enum VkVendorId { + VK_VENDOR_ID_KHRONOS = 0x10000, VK_VENDOR_ID_VIV = 0x10001, VK_VENDOR_ID_VSI = 0x10002, VK_VENDOR_ID_KAZAN = 0x10003, @@ -1366,15 +1394,15 @@ typedef struct VkComponentMapping { } VkComponentMapping; typedef struct VkExtensionProperties { - char extensionName [ VK_MAX_EXTENSION_NAME_SIZE ]; - uint32_t specVersion; + char extensionName [ VK_MAX_EXTENSION_NAME_SIZE ]; + uint32_t specVersion; } VkExtensionProperties; typedef struct VkLayerProperties { - char layerName [ VK_MAX_EXTENSION_NAME_SIZE ]; - uint32_t specVersion; - uint32_t implementationVersion; - char description [ VK_MAX_DESCRIPTION_SIZE ]; + char layerName [ VK_MAX_EXTENSION_NAME_SIZE ]; + uint32_t specVersion; + uint32_t implementationVersion; + char description [ VK_MAX_DESCRIPTION_SIZE ]; } VkLayerProperties; typedef struct VkApplicationInfo { @@ -1593,8 +1621,21 @@ typedef struct VkDebugUtilsLabelEXT { float color [4]; } VkDebugUtilsLabelEXT; +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void * pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { + VkStructureType sType; + void * pNext; + uint32_t maxCustomBorderColorSamplers; +} VkPhysicalDeviceCustomBorderColorPropertiesEXT; + /* Complete version of this file */ -#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 4, VK_HEADER_VERSION) typedef uint32_t VkSampleMask; typedef uint32_t VkBool32; typedef uint32_t VkFlags; @@ -2576,6 +2617,70 @@ typedef struct VkSwapchainCreateInfoKHR { VkSwapchainKHR oldSwapchain; } VkSwapchainCreateInfoKHR; +typedef struct VkPhysicalDeviceFeatures2 { + VkStructureType sType; + void * pNext; + VkPhysicalDeviceFeatures features; +} VkPhysicalDeviceFeatures2; + +typedef struct VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; + +typedef struct VkFormatProperties2 { + VkStructureType sType; + void * pNext; + VkFormatProperties formatProperties; +} VkFormatProperties2; + +typedef struct VkFormatProperties2 VkFormatProperties2KHR; + +typedef struct VkImageFormatProperties2 { + VkStructureType sType; + void * pNext; + VkImageFormatProperties imageFormatProperties; +} VkImageFormatProperties2; + +typedef struct VkImageFormatProperties2 VkImageFormatProperties2KHR; + +typedef struct VkPhysicalDeviceImageFormatInfo2 { + VkStructureType sType; + const void * pNext; + VkFormat format; + VkImageType type; + VkImageTiling tiling; + VkImageUsageFlags usage; + VkImageCreateFlags flags; +} VkPhysicalDeviceImageFormatInfo2; + +typedef struct VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR; + +typedef struct VkQueueFamilyProperties2 { + VkStructureType sType; + void * pNext; + VkQueueFamilyProperties queueFamilyProperties; +} VkQueueFamilyProperties2; + +typedef struct VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR; + +typedef struct VkSparseImageFormatProperties2 { + VkStructureType sType; + void * pNext; + VkSparseImageFormatProperties properties; +} VkSparseImageFormatProperties2; + +typedef struct VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; + +typedef struct VkPhysicalDeviceSparseImageFormatInfo2 { + VkStructureType sType; + const void * pNext; + VkFormat format; + VkImageType type; + VkSampleCountFlagBits samples; + VkImageUsageFlags usage; + VkImageTiling tiling; +} VkPhysicalDeviceSparseImageFormatInfo2; + +typedef struct VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; + typedef struct VkDeviceGroupPresentCapabilitiesKHR { VkStructureType sType; void * pNext; @@ -2595,7 +2700,7 @@ typedef struct VkDebugUtilsMessengerCallbackDataEXT { VkDebugUtilsMessengerCallbackDataFlagsEXT flags; const char * pMessageIdName; int32_t messageIdNumber; - const char * pMessage; + const char * pMessage; uint32_t queueLabelCount; const VkDebugUtilsLabelEXT * pQueueLabels; uint32_t cmdBufLabelCount; @@ -2604,6 +2709,13 @@ typedef struct VkDebugUtilsMessengerCallbackDataEXT { const VkDebugUtilsObjectNameInfoEXT * pObjects; } VkDebugUtilsMessengerCallbackDataEXT; +typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { + VkStructureType sType; + void * pNext; + VkBool32 customBorderColors; + VkBool32 customBorderColorWithoutFormat; +} VkPhysicalDeviceCustomBorderColorFeaturesEXT; + typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, @@ -2635,12 +2747,28 @@ typedef struct VkDeviceCreateInfo { } VkDeviceCreateInfo; typedef struct VkPhysicalDeviceMemoryProperties { - uint32_t memoryTypeCount; + uint32_t memoryTypeCount; VkMemoryType memoryTypes [ VK_MAX_MEMORY_TYPES ]; - uint32_t memoryHeapCount; + uint32_t memoryHeapCount; VkMemoryHeap memoryHeaps [ VK_MAX_MEMORY_HEAPS ]; } VkPhysicalDeviceMemoryProperties; +typedef struct VkPhysicalDeviceProperties2 { + VkStructureType sType; + void * pNext; + VkPhysicalDeviceProperties properties; +} VkPhysicalDeviceProperties2; + +typedef struct VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; + +typedef struct VkPhysicalDeviceMemoryProperties2 { + VkStructureType sType; + void * pNext; + VkPhysicalDeviceMemoryProperties memoryProperties; +} VkPhysicalDeviceMemoryProperties2; + +typedef struct VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR; + typedef struct VkDebugUtilsMessengerCreateInfoEXT { VkStructureType sType; const void * pNext; @@ -2655,8 +2783,12 @@ typedef struct VkDebugUtilsMessengerCreateInfoEXT { #define VK_VERSION_1_0 1 GLAD_API_CALL int GLAD_VK_VERSION_1_0; +#define VK_EXT_custom_border_color 1 +GLAD_API_CALL int GLAD_VK_EXT_custom_border_color; #define VK_EXT_debug_utils 1 GLAD_API_CALL int GLAD_VK_EXT_debug_utils; +#define VK_KHR_get_physical_device_properties2 1 +GLAD_API_CALL int GLAD_VK_KHR_get_physical_device_properties2; #define VK_KHR_surface 1 GLAD_API_CALL int GLAD_VK_KHR_surface; #define VK_KHR_swapchain 1 @@ -2806,13 +2938,20 @@ typedef void (GLAD_API_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice dev typedef void (GLAD_API_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource * pSubresource, VkSubresourceLayout * pLayout); typedef PFN_vkVoidFunction (GLAD_API_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char * pName); typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures * pFeatures); +typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2 * pFeatures); typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties * pFormatProperties); +typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2 * pFormatProperties); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties * pImageFormatProperties); +typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo, VkImageFormatProperties2 * pImageFormatProperties); typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties * pMemoryProperties); +typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2 * pMemoryProperties); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pRectCount, VkRect2D * pRects); typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties * pProperties); +typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 * pProperties); typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t * pQueueFamilyPropertyCount, VkQueueFamilyProperties * pQueueFamilyProperties); +typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t * pQueueFamilyPropertyCount, VkQueueFamilyProperties2 * pQueueFamilyProperties); typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t * pPropertyCount, VkSparseImageFormatProperties * pProperties); +typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo, uint32_t * pPropertyCount, VkSparseImageFormatProperties2 * pProperties); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR * pSurfaceCapabilities); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pSurfaceFormatCount, VkSurfaceFormatKHR * pSurfaceFormats); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pPresentModeCount, VkPresentModeKHR * pPresentModes); @@ -3112,20 +3251,34 @@ GLAD_API_CALL PFN_vkGetInstanceProcAddr glad_vkGetInstanceProcAddr; #define vkGetInstanceProcAddr glad_vkGetInstanceProcAddr GLAD_API_CALL PFN_vkGetPhysicalDeviceFeatures glad_vkGetPhysicalDeviceFeatures; #define vkGetPhysicalDeviceFeatures glad_vkGetPhysicalDeviceFeatures +GLAD_API_CALL PFN_vkGetPhysicalDeviceFeatures2KHR glad_vkGetPhysicalDeviceFeatures2KHR; +#define vkGetPhysicalDeviceFeatures2KHR glad_vkGetPhysicalDeviceFeatures2KHR GLAD_API_CALL PFN_vkGetPhysicalDeviceFormatProperties glad_vkGetPhysicalDeviceFormatProperties; #define vkGetPhysicalDeviceFormatProperties glad_vkGetPhysicalDeviceFormatProperties +GLAD_API_CALL PFN_vkGetPhysicalDeviceFormatProperties2KHR glad_vkGetPhysicalDeviceFormatProperties2KHR; +#define vkGetPhysicalDeviceFormatProperties2KHR glad_vkGetPhysicalDeviceFormatProperties2KHR GLAD_API_CALL PFN_vkGetPhysicalDeviceImageFormatProperties glad_vkGetPhysicalDeviceImageFormatProperties; #define vkGetPhysicalDeviceImageFormatProperties glad_vkGetPhysicalDeviceImageFormatProperties +GLAD_API_CALL PFN_vkGetPhysicalDeviceImageFormatProperties2KHR glad_vkGetPhysicalDeviceImageFormatProperties2KHR; +#define vkGetPhysicalDeviceImageFormatProperties2KHR glad_vkGetPhysicalDeviceImageFormatProperties2KHR GLAD_API_CALL PFN_vkGetPhysicalDeviceMemoryProperties glad_vkGetPhysicalDeviceMemoryProperties; #define vkGetPhysicalDeviceMemoryProperties glad_vkGetPhysicalDeviceMemoryProperties +GLAD_API_CALL PFN_vkGetPhysicalDeviceMemoryProperties2KHR glad_vkGetPhysicalDeviceMemoryProperties2KHR; +#define vkGetPhysicalDeviceMemoryProperties2KHR glad_vkGetPhysicalDeviceMemoryProperties2KHR GLAD_API_CALL PFN_vkGetPhysicalDevicePresentRectanglesKHR glad_vkGetPhysicalDevicePresentRectanglesKHR; #define vkGetPhysicalDevicePresentRectanglesKHR glad_vkGetPhysicalDevicePresentRectanglesKHR GLAD_API_CALL PFN_vkGetPhysicalDeviceProperties glad_vkGetPhysicalDeviceProperties; #define vkGetPhysicalDeviceProperties glad_vkGetPhysicalDeviceProperties +GLAD_API_CALL PFN_vkGetPhysicalDeviceProperties2KHR glad_vkGetPhysicalDeviceProperties2KHR; +#define vkGetPhysicalDeviceProperties2KHR glad_vkGetPhysicalDeviceProperties2KHR GLAD_API_CALL PFN_vkGetPhysicalDeviceQueueFamilyProperties glad_vkGetPhysicalDeviceQueueFamilyProperties; #define vkGetPhysicalDeviceQueueFamilyProperties glad_vkGetPhysicalDeviceQueueFamilyProperties +GLAD_API_CALL PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR glad_vkGetPhysicalDeviceQueueFamilyProperties2KHR; +#define vkGetPhysicalDeviceQueueFamilyProperties2KHR glad_vkGetPhysicalDeviceQueueFamilyProperties2KHR GLAD_API_CALL PFN_vkGetPhysicalDeviceSparseImageFormatProperties glad_vkGetPhysicalDeviceSparseImageFormatProperties; #define vkGetPhysicalDeviceSparseImageFormatProperties glad_vkGetPhysicalDeviceSparseImageFormatProperties +GLAD_API_CALL PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR glad_vkGetPhysicalDeviceSparseImageFormatProperties2KHR; +#define vkGetPhysicalDeviceSparseImageFormatProperties2KHR glad_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GLAD_API_CALL PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR glad_vkGetPhysicalDeviceSurfaceCapabilitiesKHR; #define vkGetPhysicalDeviceSurfaceCapabilitiesKHR glad_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GLAD_API_CALL PFN_vkGetPhysicalDeviceSurfaceFormatsKHR glad_vkGetPhysicalDeviceSurfaceFormatsKHR; @@ -3246,7 +3399,9 @@ extern "C" { int GLAD_VK_VERSION_1_0 = 0; +int GLAD_VK_EXT_custom_border_color = 0; int GLAD_VK_EXT_debug_utils = 0; +int GLAD_VK_KHR_get_physical_device_properties2 = 0; int GLAD_VK_KHR_surface = 0; int GLAD_VK_KHR_swapchain = 0; #if defined(VK_USE_PLATFORM_WIN32_KHR) @@ -3393,13 +3548,20 @@ PFN_vkGetImageSparseMemoryRequirements glad_vkGetImageSparseMemoryRequirements = PFN_vkGetImageSubresourceLayout glad_vkGetImageSubresourceLayout = NULL; PFN_vkGetInstanceProcAddr glad_vkGetInstanceProcAddr = NULL; PFN_vkGetPhysicalDeviceFeatures glad_vkGetPhysicalDeviceFeatures = NULL; +PFN_vkGetPhysicalDeviceFeatures2KHR glad_vkGetPhysicalDeviceFeatures2KHR = NULL; PFN_vkGetPhysicalDeviceFormatProperties glad_vkGetPhysicalDeviceFormatProperties = NULL; +PFN_vkGetPhysicalDeviceFormatProperties2KHR glad_vkGetPhysicalDeviceFormatProperties2KHR = NULL; PFN_vkGetPhysicalDeviceImageFormatProperties glad_vkGetPhysicalDeviceImageFormatProperties = NULL; +PFN_vkGetPhysicalDeviceImageFormatProperties2KHR glad_vkGetPhysicalDeviceImageFormatProperties2KHR = NULL; PFN_vkGetPhysicalDeviceMemoryProperties glad_vkGetPhysicalDeviceMemoryProperties = NULL; +PFN_vkGetPhysicalDeviceMemoryProperties2KHR glad_vkGetPhysicalDeviceMemoryProperties2KHR = NULL; PFN_vkGetPhysicalDevicePresentRectanglesKHR glad_vkGetPhysicalDevicePresentRectanglesKHR = NULL; PFN_vkGetPhysicalDeviceProperties glad_vkGetPhysicalDeviceProperties = NULL; +PFN_vkGetPhysicalDeviceProperties2KHR glad_vkGetPhysicalDeviceProperties2KHR = NULL; PFN_vkGetPhysicalDeviceQueueFamilyProperties glad_vkGetPhysicalDeviceQueueFamilyProperties = NULL; +PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR glad_vkGetPhysicalDeviceQueueFamilyProperties2KHR = NULL; PFN_vkGetPhysicalDeviceSparseImageFormatProperties glad_vkGetPhysicalDeviceSparseImageFormatProperties = NULL; +PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR glad_vkGetPhysicalDeviceSparseImageFormatProperties2KHR = NULL; PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR glad_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = NULL; PFN_vkGetPhysicalDeviceSurfaceFormatsKHR glad_vkGetPhysicalDeviceSurfaceFormatsKHR = NULL; PFN_vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDeviceSurfacePresentModesKHR = NULL; @@ -3594,6 +3756,16 @@ static void glad_vk_load_VK_EXT_debug_utils( GLADuserptrloadfunc load, void* use glad_vkSetDebugUtilsObjectTagEXT = (PFN_vkSetDebugUtilsObjectTagEXT) load(userptr, "vkSetDebugUtilsObjectTagEXT"); glad_vkSubmitDebugUtilsMessageEXT = (PFN_vkSubmitDebugUtilsMessageEXT) load(userptr, "vkSubmitDebugUtilsMessageEXT"); } +static void glad_vk_load_VK_KHR_get_physical_device_properties2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_VK_KHR_get_physical_device_properties2) return; + glad_vkGetPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR) load(userptr, "vkGetPhysicalDeviceFeatures2KHR"); + glad_vkGetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR) load(userptr, "vkGetPhysicalDeviceFormatProperties2KHR"); + glad_vkGetPhysicalDeviceImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR) load(userptr, "vkGetPhysicalDeviceImageFormatProperties2KHR"); + glad_vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR) load(userptr, "vkGetPhysicalDeviceMemoryProperties2KHR"); + glad_vkGetPhysicalDeviceProperties2KHR = (PFN_vkGetPhysicalDeviceProperties2KHR) load(userptr, "vkGetPhysicalDeviceProperties2KHR"); + glad_vkGetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR) load(userptr, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"); + glad_vkGetPhysicalDeviceSparseImageFormatProperties2KHR = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR) load(userptr, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"); +} static void glad_vk_load_VK_KHR_surface( GLADuserptrloadfunc load, void* userptr) { if(!GLAD_VK_KHR_surface) return; glad_vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) load(userptr, "vkDestroySurfaceKHR"); @@ -3760,7 +3932,9 @@ static int glad_vk_find_extensions_vulkan( VkPhysicalDevice physical_device) { char **extensions = NULL; if (!glad_vk_get_extensions(physical_device, &extension_count, &extensions)) return 0; + GLAD_VK_EXT_custom_border_color = glad_vk_has_extension("VK_EXT_custom_border_color", extension_count, extensions); GLAD_VK_EXT_debug_utils = glad_vk_has_extension("VK_EXT_debug_utils", extension_count, extensions); + GLAD_VK_KHR_get_physical_device_properties2 = glad_vk_has_extension("VK_KHR_get_physical_device_properties2", extension_count, extensions); GLAD_VK_KHR_surface = glad_vk_has_extension("VK_KHR_surface", extension_count, extensions); GLAD_VK_KHR_swapchain = glad_vk_has_extension("VK_KHR_swapchain", extension_count, extensions); #if defined(VK_USE_PLATFORM_WIN32_KHR) @@ -3824,6 +3998,7 @@ int gladLoadVulkanUserPtr( VkPhysicalDevice physical_device, GLADuserptrloadfunc if (!glad_vk_find_extensions_vulkan( physical_device)) return 0; glad_vk_load_VK_EXT_debug_utils(load, userptr); + glad_vk_load_VK_KHR_get_physical_device_properties2(load, userptr); glad_vk_load_VK_KHR_surface(load, userptr); glad_vk_load_VK_KHR_swapchain(load, userptr); #if defined(VK_USE_PLATFORM_WIN32_KHR) diff --git a/intermediate/triangle.glsl b/intermediate/triangle.glsl index 04f66d3..beee129 100644 --- a/intermediate/triangle.glsl +++ b/intermediate/triangle.glsl @@ -13,20 +13,33 @@ type: vec2 [attribute] name: colour type: vec3 +[attribute] +name: uv +type: vec2 [interpolator] name: colour type: vec3 +[interpolator] +name: uv +type: vec2 [target] name: colour type: vec4 + +[texture] +name: colour_texture +stage: fragment +dimension: 2 + #endif #ifdef VERTEX_SHADER void main() { - interpolator.colour = vec3(colour); + interpolator.colour = colour; + interpolator.uv = uv; gl_Position = vec4(position, 0.0, 1.0); } @@ -35,7 +48,9 @@ void main() { #ifdef FRAGMENT_SHADER void main() { - colour = vec4(interpolator.colour, 1.0); + vec3 c = texture(colour_texture, interpolator.uv).rgb; +// c *= interpolator.colour; + colour = vec4(c, 1.0); } #endif diff --git a/pipeline.cpp b/pipeline.cpp index ce95672..1715930 100644 --- a/pipeline.cpp +++ b/pipeline.cpp @@ -32,12 +32,30 @@ void Pipeline_Builder::begin() { pip = (Pipeline*)arena_alloc(arena, sizeof *pip); pip->vertex_format = 0; pip->shader = 0; + pip->descriptors = 0; } void Pipeline_Builder::shader(Shader_Id s) { pip->shader = s; } +void Pipeline_Builder::texture( + int binding, + Texture_Id t, + Sampler_Id s +) { + Texture_Descriptor* d = (Texture_Descriptor*)arena_alloc( + arena, + sizeof *d + ); + d->slot = binding; + d->type = Descriptor::Type::texture; + d->sampler = s; + d->texture = t; + d->next = pip->descriptors; + pip->descriptors = d; +} + void Pipeline_Builder::vertex_format(Vertex_Format_Id vf) { pip->vertex_format = vf; } diff --git a/sc/sc.cpp b/sc/sc.cpp index 6218f7a..f7acc1a 100644 --- a/sc/sc.cpp +++ b/sc/sc.cpp @@ -7,11 +7,15 @@ extern "C" { #include "cfgparse.h" #include "plat.h" #include "sh_enums.h" +#include "str.h" } #include -#include #include +#include +#include +#include +#include const char* glsl_version_s = "#version 440 core"; const int glsl_version = 440; @@ -82,6 +86,12 @@ static const char* program_type_strings[] = { #undef x }; +static const char* stage_strings[] = { +#define x(n) #n, + shader_type_xmacro() +#undef x +}; + static const char* type_strings[] = { #define x(n) #n, svariable_type_xmacro() @@ -120,6 +130,16 @@ int type_from_string(const char* s) { return 0; } +int stage_from_string(const char* s) { + int i; + for (i = 0; i < shader_type_count; i++) + if (!strcmp(stage_strings[i], s)) + return i; + print_err("Invalid stage type %s\n", s); + pbreak(800); + return 0; +} + SBinding_Rate rate_from_string(const char* s) { int i; for (i = 0; i < sbinding_rate_count; i++) { @@ -142,10 +162,21 @@ struct Desc { std::string name; std::vector attrs; }; + struct Texture { + int stage; + int dimension; + }; + struct Descriptor { + std::string name; + int slot; + int stage; + }; int type; std::vector bindings; std::vector trgts; std::vector interp; + std::unordered_map textures; + std::vector descriptors; std::string entrypoints[shader_type_count]; void read_var(Variable& d, cfg_Object* desc) { const char* sname = find_string_default(desc, "name", 0); @@ -186,6 +217,32 @@ struct Desc { } return &b; } + void read_texture(cfg_Object* desc) { + const char* sname = find_string_default(desc, "name", 0); + if (!sname) { + print_err("%s must have a name.\n", desc->name); + pbreak(801); + } + const char* sstage = find_string_default(desc, "stage", 0); + if (!sstage) { + print_err("%s must define a stage.\n", sname); + pbreak(802); + } + std::string n = std::string(sname); + if (n.size() > 23) { + print_err("Texture name %s is too long (max 23 chars).\n", sname); + + pbreak(803); + } + if (!textures.contains(n)) { + Texture& t = textures[n]; + t.stage = 0; + t.dimension = 0; + } + Texture& t = textures[n]; + t.stage |= 1 << stage_from_string(sstage); + t.dimension = find_int_default(desc, "dimension", 2); + } void build(cfg_Object* desc) { int i; Binding* cur_binding = 0; @@ -230,12 +287,54 @@ struct Desc { } else if (!strcmp(desc->name, "interpolator")) { read_var(v, desc); interp.push_back(v); + } else if (!strcmp(desc->name, "texture")) { + read_texture(desc); } desc = desc->next; } + build_descriptors(); + } + + Descriptor* find_desc(const char* name) { + int count = descriptors.size(); + int i, bucket = (int)(hash_string(name) % count); + for (i = 0; i < count; i++) { + Descriptor& d = descriptors[bucket]; + if ( + d.name.empty() || + !strcmp(name, d.name.c_str()) + ) return &d; + bucket = (bucket + 1) % count; + } + return 0; + }; + + void build_descriptors() { + int slot = 0; + descriptors.resize(textures.size()); + for (auto& i : textures) { + Descriptor* d = find_desc(i.first.c_str()); + d->name = i.first; + d->slot = slot; + d->stage = i.second.stage; + slot++; + } + } + + void add_textures(std::stringstream& ss, Shader_Type stage) { + for (const auto& it : textures) { + const auto& texture = it.second; + if (texture.stage & (1 << stage)) { + Descriptor* d = find_desc(it.first.c_str()); + assert(d != 0); + ss << "layout (binding = " << d->slot << ") "; + ss << "uniform sampler" << texture.dimension << "D "; + ss << it.first << ";\n"; + } + } } - std::string build_vs() const { + std::string build_vs() { std::stringstream ss; size_t i, li = bindings.size(); size_t l = 0; @@ -253,10 +352,11 @@ struct Desc { for (const auto& i : interp) ss << i.tname << " " << i.name << ";\n"; ss << "} interpolator;\n"; + add_textures(ss, shader_type_vertex); return ss.str(); } - std::string build_fs() const { + std::string build_fs() { std::stringstream ss; size_t i, l = trgts.size(); for (i = 0; i < l; i++) { @@ -269,12 +369,13 @@ struct Desc { for (const auto& i : interp) ss << i.tname << " " << i.name << ";\n"; ss << "} interpolator;\n"; + add_textures(ss, shader_type_fragment); return ss.str(); } }; std::vector compile_shader( - const Desc& d, + Desc& d, const char* presrc, const char* src, const char* define, @@ -345,7 +446,7 @@ std::vector compile_shader( } void configure( - const Desc& d, + Desc& d, int stage, const char*& dfn, EShLanguage& l, @@ -368,7 +469,7 @@ void configure( void compile_shaders( std::vector* spv, const char* src, - const Desc& d + Desc& d ) { const char* define; EShLanguage lang; @@ -394,7 +495,7 @@ void write_csh( const Desc& d, const std::vector* stages ) { - int hsize = 16, i, coff; + int hsize = 20, i, coff; FILE* f = fopen(fname, "wb"); if (!f) { print_err("Failed to open %s\n", fname); @@ -405,6 +506,7 @@ void write_csh( fwrite(&d.type, 4, 1, f); c = d.bindings.size(); fwrite(&c, 4, 1, f); c = d.trgts.size(); fwrite(&c, 4, 1, f); + c = d.descriptors.size(); fwrite(&c, 4, 1, f); for (const auto& b : d.bindings) { char buf[24]; int count = b.attrs.size(); @@ -431,6 +533,15 @@ void write_csh( fwrite(&t.type, 4, 1, f); hsize += 32; } + for (const auto& d : d.descriptors) { + char buf[24]; + memset(buf, 0, sizeof buf); + strcpy(buf, d.name.c_str()); + fwrite(buf, 1, sizeof buf, f); + fwrite(&d.slot, 4, 1, f); + fwrite(&d.stage, 4, 1, f); + hsize += 32; + } hsize += shader_type_count * 32; for (i = 0, coff = 0; i < shader_type_count; i++) { int o = 0; diff --git a/video.cpp b/video.cpp index 8bc5080..d6180bd 100644 --- a/video.cpp +++ b/video.cpp @@ -8,6 +8,7 @@ #define max_rpos 64 #define max_pipelines 64 #define max_shaders 32 +#define max_samplers 16 extern "C" { #include "memory.h" @@ -27,7 +28,8 @@ extern "C" { #include "glad_vk.h" const char* device_exts[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME }; extern "C" { @@ -388,10 +390,18 @@ struct Shader_Vk : public Shader, public Late_Terminated { int find_attribute(const char* name); }; + struct Desc { + char name[24]; + int slot; + int stage; + }; + SProgram_Type type; VkShaderModule modules[shader_type_count]; char entrypoints[shader_type_count][24]; Vertex_Format vfd; + Desc* descs; + int desc_count; bool init(Device_Vk* dev, Pack_File* f); bool init_module( @@ -406,6 +416,8 @@ struct Shader_Vk : public Shader, public Late_Terminated { ); void destroy(Device_Vk* dev) override; + int find_descriptor(const char* name); + static VkShaderStageFlagBits stage(Shader_Type type) { switch (type) { case shader_type_vertex: @@ -519,6 +531,9 @@ struct Pso_Key { struct Pipeline_Vk { VkPipeline pip; VkPipelineLayout lay; + VkDescriptorPool dp; + VkDescriptorSet dset; + VkDescriptorSetLayout dlay; int age; void init(Device_Vk* dev, const Pso_Key& desc); @@ -576,6 +591,11 @@ struct Pipeline_Vk { Device_Vk* dev, const Pipeline& desc ); + void init_descriptors( + Device_Vk* dev, + const Pipeline& desc, + int count + ); void on_submit() { age = 0; @@ -594,6 +614,17 @@ struct Vertex_Format_Vk { static VkFormat format_from_svar_type(SVariable_Type type); }; +struct Sampler_Vk : public Late_Terminated { + VkSampler sampler; + + void init(Device_Vk* dev, const Sampler_State& s); + void destroy(Device_Vk* dev) override; + + static VkFilter get_filter(Filter_Mode mode); + static VkSamplerMipmapMode get_mipmap_mode(Filter_Mode mode); + static VkSamplerAddressMode get_mode(Address_Mode mode); +}; + template<> struct Hash_Function { @@ -638,6 +669,13 @@ struct Hash_Function { } }; +template<> +struct Hash_Function { + size_t operator()(Sampler_Id id) const { + return id.index; + } +}; + template<> struct std::hash { size_t operator()(const Render_Pass& rp) const { @@ -717,10 +755,12 @@ struct Device_Vk : public Device { max_vertex_formats > vertex_formats; Hash_Map shaders; + Hash_Map samplers; uint32_t texture_count; uint32_t buffer_count; uint32_t vertex_format_count; uint32_t shader_count; + uint32_t sampler_count; Hash_Map rpo_cache; Hash_Map pso_cache; @@ -734,6 +774,7 @@ struct Device_Vk : public Device { Vertex_Format_Id create_vf(Shader_Vk& shader); void destroy_vf(Vertex_Format_Id id); Shader_Id alloc_shader(); + Sampler_Id alloc_sampler(); void init_internal(); void deinit_internal(); @@ -874,6 +915,7 @@ bool Device_Vk::has_validation() { void Device_Vk::find_exts(const char** exts, int& count) { app->get_vk_exts(exts, count); + exts[count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; #ifdef DEBUG exts[count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; #endif @@ -1023,11 +1065,14 @@ VkPhysicalDevice get_phys_dev(Device_Vk* d, Swap_Cap* sc) { void Device_Vk::create_dev(Swap_Cap* swap_cap) { const float priority = 0.0f; VkDeviceQueueCreateInfo qi{}; + VkPhysicalDeviceCustomBorderColorFeaturesEXT border{}; VkDeviceCreateInfo di{}; VkPhysicalDeviceFeatures pdf{}; VkResult r; phys_dev = get_phys_dev(this, swap_cap); vkGetPhysicalDeviceMemoryProperties(phys_dev, &mem_props); + border.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; + border.customBorderColors = true; qi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; qi.queueFamilyIndex = queue_index; qi.queueCount = 1; @@ -1039,7 +1084,7 @@ void Device_Vk::create_dev(Swap_Cap* swap_cap) { di.enabledExtensionCount = sizeof device_exts / sizeof *device_exts; di.ppEnabledExtensionNames = device_exts; - di.pNext = 0; + di.pNext = &border; r = vkCreateDevice( phys_dev, &di, @@ -1064,6 +1109,8 @@ void Device_Vk::init_internal() { vertex_format_count = 1; shaders.init(); shader_count = 1; + samplers.init(); + sampler_count = 1; rpo_cache.init(); pso_cache.init(); shader_loader.init(this); @@ -1545,6 +1592,7 @@ Texture& Device::get_texture(Texture_Id id) { Texture_Id Device_Vk::alloc_texture() { Texture_Vk tex{}; Texture_Id id(texture_count++); + tex.id = id; textures.set(id, tex); return id; } @@ -1552,6 +1600,7 @@ Texture_Id Device_Vk::alloc_texture() { Buffer_Id Device_Vk::alloc_buffer() { Buffer_Vk buf{}; Buffer_Id id(buffer_count++); + buf.id = id; buffers.set(id, buf); return id; } @@ -1577,11 +1626,17 @@ void Device_Vk::destroy_vf(Vertex_Format_Id id) { Shader_Id Device_Vk::alloc_shader() { Shader_Vk buf{}; Shader_Id id(shader_count++); - assert(id.index < max_shaders); shaders.set(id, buf); return id; } +Sampler_Id Device_Vk::alloc_sampler() { + Sampler_Vk s{}; + Sampler_Id id(sampler_count++); + samplers.set(id, s); + return id; +} + void Device::destroy_texture(Texture_Id id) { Device_Vk* dev = (Device_Vk*)this; dev->queue_destroy((Texture_Vk*)&dev->get_texture(id)); @@ -1615,6 +1670,16 @@ void Context::submit( VK_PIPELINE_BIND_POINT_GRAPHICS, pso.pip ); + vkCmdBindDescriptorSets( + ctx->cb, + VK_PIPELINE_BIND_POINT_GRAPHICS, + pso.lay, + 0, + 1, + &pso.dset, + 0, + 0 + ); for (binding = draw.verts; binding->id; binding++) { VkBuffer buf = ((Buffer_Vk*)&dev->get_buffer(binding->id))->buf; VkDeviceSize offset = (VkDeviceSize)binding->offset; @@ -2101,6 +2166,143 @@ void Pipeline_Vk::init_blending( info.pColorBlendState = &bi; } +void Pipeline_Vk::init_descriptors( + Device_Vk* dev, + const Pipeline& desc, + int count +) { + int sampler_count = 0, cbuffer_count = 0; + const Descriptor* d = desc.descriptors; + Shader_Vk& shader = *(Shader_Vk*)&dev->get_shader(desc.shader); + VkDescriptorPoolSize sizes[4]; + VkResult r; + int size_count = 0, i; + for (; d; d = d->next) { + switch (d->type) { + case Descriptor::Type::texture: + sampler_count++; + break; + default: + assert(0); + break; + } + } + if (sampler_count) { + int idx = size_count++; + sizes[idx] = { + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = (uint32_t)sampler_count + }; + } + if (cbuffer_count) { + int idx = size_count++; + sizes[idx] = { + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = (uint32_t)cbuffer_count + }; + } + { + VkDescriptorPoolCreateInfo di{}; + di.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + di.poolSizeCount = (uint32_t)size_count; + di.pPoolSizes = sizes; + di.maxSets = (uint32_t)count; + r = vkCreateDescriptorPool(dev->dev, &di, &dev->ac, &dp); + if (r != VK_SUCCESS) { + print_err("Failed to create a descriptor pool.\n"); + pbreak(r); + } + } + { + VkDescriptorSetLayoutBinding* descs = + (VkDescriptorSetLayoutBinding*)heap_alloc( + dev->heap, + count * sizeof *descs + ); + VkDescriptorSetLayoutCreateInfo di{}; + VkDescriptorSetAllocateInfo da{}; + memset(descs, 0, count * sizeof *descs); + Descriptor* src = desc.descriptors; + for (i = count - 1; i >= 0; i--) { + int j, stage; + auto& dst = descs[i]; + switch (src->type) { + case Descriptor::Type::texture: + dst.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + break; + default: + assert(0); + break; + } + dst.binding = src->slot; + dst.descriptorCount = 1; + dst.stageFlags = 0; + stage = shader.descriptor_stage(src->slot); + for (j = 0; j < shader_type_count; j++) { + if (stage & (1 << j)) { + dst.stageFlags |= Shader_Vk::stage((Shader_Type)j); + } + } + src = src->next; + } + di.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + di.bindingCount = (uint32_t)count; + di.pBindings = descs; + r = vkCreateDescriptorSetLayout( + dev->dev, + &di, + &dev->ac, + &dlay + ); + if (r != VK_SUCCESS) { + print_err("Failed to create descriptor set layout.\n"); + pbreak(r); + } + da.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + da.descriptorPool = dp; + da.descriptorSetCount = 1; + da.pSetLayouts = &dlay; + r = vkAllocateDescriptorSets( + dev->dev, + &da, + &dset + ); + /* todo this should be refactored to allow + * swapping the resources without recreating pipelines */ + src = desc.descriptors; + for (i = 0; i < count; i++) { + VkDescriptorImageInfo img{}; + VkWriteDescriptorSet wd{}; + wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + wd.dstSet = dset; + wd.dstBinding = src->slot; + wd.dstArrayElement = 0; + wd.descriptorCount = 1; + + switch (src->type) { + case Descriptor::Type::texture: { + Texture_Descriptor* td = (Texture_Descriptor*)src; + assert(td->texture); + assert(td->sampler); + Texture_Vk& t = *(Texture_Vk*)&dev->get_texture(td->texture); + Sampler_Vk& s = *(Sampler_Vk*)&dev->samplers[td->sampler]; + img.imageView = t.view; + img.sampler = s.sampler; + img.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + wd.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + wd.pImageInfo = &img; + } break; + default: + assert(0); + break; + } + vkUpdateDescriptorSets(dev->dev, 1, &wd, 0, 0); + src = src->next; + } + heap_free(dev->heap, descs); + } +} + void Pipeline_Vk::init_layout( Device_Vk* dev, const Pipeline& desc @@ -2108,9 +2310,15 @@ void Pipeline_Vk::init_layout( VkResult r; VkPipelineLayoutCreateInfo li{}; (void)desc; + int desc_count = desc.count_descriptors(); + int set_count = desc_count? 1: 0; + if (set_count) { + init_descriptors(dev, desc, desc_count); + } li.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - li.setLayoutCount = 0; - li.pushConstantRangeCount = 0; /* todo */ + li.setLayoutCount = set_count; + li.pSetLayouts = &dlay; + li.pushConstantRangeCount = 0; r = vkCreatePipelineLayout( dev->dev, &li, @@ -2159,8 +2367,10 @@ void Pipeline_Vk::init(Device_Vk* dev, const Pso_Key& key) { } void Pipeline_Vk::destroy(Device_Vk* dev) { - vkDestroyPipeline(dev->dev, pip, &dev->ac); + vkDestroyDescriptorPool(dev->dev, dp, &dev->ac); + vkDestroyDescriptorSetLayout(dev->dev, dlay, &dev->ac); vkDestroyPipelineLayout(dev->dev, lay, &dev->ac); + vkDestroyPipeline(dev->dev, pip, &dev->ac); } int Vertex_Format_Vk::svariable_type_size(SVariable_Type type) { @@ -2365,6 +2575,7 @@ void Shader_Vk::destroy(Device_Vk* dev) { if (modules[i]) vkDestroyShaderModule(dev->dev, modules[i], &dev->ac); vfd.destroy(dev); + heap_free(dev->heap, descs); dev->destroy_vf(vf); dev->shaders.remove(id); } @@ -2385,6 +2596,25 @@ int Shader::attribute_index(const char* name) { return idx; } +int Shader::descriptor_index(const char* name) { + int idx; + Shader_Vk* sh = (Shader_Vk*)this; + idx = sh->find_descriptor(name); + if (idx < 0 || !sh->descs[idx].name[0]) return -1; + return idx; +} + +int Shader::descriptor_stage(int slot) { + Shader_Vk* sh = (Shader_Vk*)this; + int i; + for (i = 0; i < sh->desc_count; i++) { + if (sh->descs[i].slot == slot) { + return sh->descs[i].stage; + } + } + return 0; +} + void Buffer_Vk::init( Device_Vk* dev, int flags, @@ -2481,6 +2711,20 @@ Shader& Device::get_shader(Shader_Id id) { return ((Device_Vk*)this)->shaders[id]; } +Sampler_Id Device::create_sampler(const Sampler_State& state) { + Device_Vk* dev = (Device_Vk*)this; + Sampler_Id id = dev->alloc_sampler(); + Sampler_Vk& s = dev->samplers[id]; + s.init(dev, state); + return id; +} + +void Device::destroy_sampler(Sampler_Id id) { + Device_Vk* dev = (Device_Vk*)this; + Sampler_Vk& s = dev->samplers[id]; + dev->queue_destroy(&s); +} + void Shader_Loader::init(Device_Vk* d) { dev = d; } @@ -2509,6 +2753,20 @@ void Shader_Loader::unload(Asset* a) { dev->queue_destroy(sh); } +int Shader_Vk::find_descriptor(const char* name) { + int i; + int bucket = (int)(hash_string(name) % desc_count); + for (i = 0; i < desc_count; i++) { + Desc& desc = descs[bucket]; + if ( + !desc.name[0] || + !strcmp(desc.name, name) + ) return bucket; + bucket = (bucket + 1) % desc_count; + } + return -1; +} + bool Shader_Vk::init(Device_Vk* dev, Pack_File* f) { char magic[4]; int binding_count, target_count, i; @@ -2522,8 +2780,9 @@ bool Shader_Vk::init(Device_Vk* dev, Pack_File* f) { pack_read(f, &type, 4); pack_read(f, &binding_count, 4); pack_read(f, &target_count, 4); - vfd.binding_count = binding_count; + pack_read(f, &desc_count, 4); assert(binding_count); + vfd.binding_count = binding_count; if (!vfd.init(dev, f)) return false; vf = dev->create_vf(*this); @@ -2532,6 +2791,11 @@ bool Shader_Vk::init(Device_Vk* dev, Pack_File* f) { 32 * target_count, seek_rel_cur ); + descs = (Desc*)heap_alloc( + dev->heap, + desc_count * sizeof *descs + ); + pack_read(f, descs, desc_count * sizeof *descs); for (i = 0; i < shader_type_count; i++) { int o, s; pack_read(f, &o, 4); @@ -2655,6 +2919,7 @@ Asset* Texture_Loader::load(Arena* a, Arena* s, Pack_File* f) { int w, h; size_t size; Texture_Format fmt; + (void)a; pack_read(f, magic, 4); pack_read(f, &w, 4); pack_read(f, &h, 4); @@ -2679,7 +2944,7 @@ Asset* Texture_Loader::load(Arena* a, Arena* s, Pack_File* f) { void Texture_Loader::unload(Asset* a) { Texture_Vk* tex = (Texture_Vk*)a; - tex->destroy(dev); + dev->destroy_texture(tex->id); } void Texture_Vk::destroy(Device_Vk* dev) { @@ -2691,3 +2956,73 @@ void Texture_Vk::destroy(Device_Vk* dev) { dev->textures.remove(id); } +VkFilter Sampler_Vk::get_filter(Filter_Mode mode) { + switch (mode) { + case Filter_Mode::point: return VK_FILTER_NEAREST; + case Filter_Mode::linear: return VK_FILTER_LINEAR; + } + assert(0); + return (VkFilter)0; +} + +VkSamplerMipmapMode Sampler_Vk::get_mipmap_mode( + Filter_Mode mode +) { + switch (mode) { + case Filter_Mode::point: + return VK_SAMPLER_MIPMAP_MODE_NEAREST; + case Filter_Mode::linear: + return VK_SAMPLER_MIPMAP_MODE_LINEAR; + } + assert(0); + return (VkSamplerMipmapMode)0; +} + +VkSamplerAddressMode Sampler_Vk::get_mode( + Address_Mode mode +) { + switch (mode) { + case Address_Mode::repeat: + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + case Address_Mode::mirror: + return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + case Address_Mode::clamp: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + case Address_Mode::border: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + } + assert(0); + return (VkSamplerAddressMode)0; +} + +void Sampler_Vk::init(Device_Vk* dev, const Sampler_State& s) { + VkSamplerCreateInfo si{}; + VkSamplerCustomBorderColorCreateInfoEXT bi{}; + VkClearColorValue col{}; + VkResult r; + col.float32[0] = s.border[0]; + col.float32[1] = s.border[1]; + col.float32[2] = s.border[2]; + col.float32[3] = s.border[3]; + si.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + si.magFilter = get_filter(s.mag); + si.minFilter = get_filter(s.min); + si.mipmapMode = get_mipmap_mode(s.mip); + si.addressModeU = get_mode(s.address_u); + si.addressModeV = get_mode(s.address_v); + si.addressModeW = get_mode(s.address_w); + si.borderColor = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT; + si.pNext = &bi; + bi.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT; + bi.customBorderColor = col; + bi.format = VK_FORMAT_R32G32B32A32_SFLOAT; + r = vkCreateSampler(dev->dev, &si, &dev->ac, &sampler); + if (r != VK_SUCCESS) { + print_err("Failed to create a sampler.\n"); + pbreak(r); + } +} + +void Sampler_Vk::destroy(Device_Vk* dev) { + vkDestroySampler(dev->dev, sampler, &dev->ac); +} diff --git a/video.hpp b/video.hpp index f05af57..dc0574e 100644 --- a/video.hpp +++ b/video.hpp @@ -39,10 +39,35 @@ struct Vertex_Format_Id : public Primitive_Id { struct Shader_Id : public Primitive_Id { using Primitive_Id::Primitive_Id; }; +struct Sampler_Id : public Primitive_Id { + using Primitive_Id::Primitive_Id; +}; + +struct Descriptor { + enum class Type { + texture + } type; + int slot; + Descriptor* next; +}; + +struct Texture_Descriptor : public Descriptor { + Sampler_Id sampler; + Texture_Id texture; +}; struct Pipeline { Vertex_Format_Id vertex_format; Shader_Id shader; + Descriptor* descriptors; + + int count_descriptors() const { + const Descriptor* d = descriptors; + int c = 0; + for (; d; d = d->next) + c++; + return c; + } }; struct Colour { @@ -92,6 +117,7 @@ struct Pipeline_Builder { void begin(); void shader(Shader_Id s); void vertex_format(Vertex_Format_Id vf); + void texture(int binding, Texture_Id t, Sampler_Id s); Pipeline& build(); void validate(); }; @@ -126,6 +152,30 @@ struct Buffer { Buffer_Id id; }; +enum class Filter_Mode { + point, + linear +}; + +enum class Address_Mode { + repeat, + mirror, + clamp, + border +}; + +struct Sampler_State { + Filter_Mode min; + Filter_Mode mag; + Filter_Mode mip; + Address_Mode address_u; + Address_Mode address_v; + Address_Mode address_w; + float border[4]; + float mip_bias; + bool aniso; +}; + struct Context; struct Shader; struct Device { @@ -156,6 +206,9 @@ struct Device { void destroy_buffer(Buffer_Id id); Shader& get_shader(Shader_Id id); + + Sampler_Id create_sampler(const Sampler_State& state); + void destroy_sampler(Sampler_Id id); }; struct Context { @@ -186,6 +239,8 @@ struct Shader : public Asset { int binding_index(const char* name); int attribute_index(const char* name); int target_index(const char* name); + int descriptor_index(const char* name); + int descriptor_stage(int slot); }; #endif -- cgit v1.2.3-54-g00ecf