summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-23 21:30:13 +1100
committerquou <quou@disroot.org>2024-12-23 21:30:13 +1100
commit078b97e48b5ad5fcf3f5a16bb081ea0efb1f931b (patch)
treed04bfb2d25952b214a4df303823ff7c5d2743681
parentb293168cc158d65f1a5146f155921ff82119d1bc (diff)
send textures to shaders
-rw-r--r--c2.cpp23
-rw-r--r--glad_vk.h211
-rw-r--r--intermediate/triangle.glsl19
-rw-r--r--pipeline.cpp18
-rw-r--r--sc/sc.cpp125
-rw-r--r--video.cpp351
-rw-r--r--video.hpp55
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>("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 <sstream>
-#include <tuple>
#include <stdint.h>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <vector>
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<Variable> attrs;
};
+ struct Texture {
+ int stage;
+ int dimension;
+ };
+ struct Descriptor {
+ std::string name;
+ int slot;
+ int stage;
+ };
int type;
std::vector<Binding> bindings;
std::vector<Variable> trgts;
std::vector<Variable> interp;
+ std::unordered_map<std::string, Texture> textures;
+ std::vector<Descriptor> 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<uint32_t> compile_shader(
- const Desc& d,
+ Desc& d,
const char* presrc,
const char* src,
const char* define,
@@ -345,7 +446,7 @@ std::vector<uint32_t> 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<uint32_t>* 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<uint32_t>* 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<Render_Pass>
{
@@ -639,6 +670,13 @@ struct Hash_Function<Vertex_Format_Id> {
};
template<>
+struct Hash_Function<Sampler_Id> {
+ size_t operator()(Sampler_Id id) const {
+ return id.index;
+ }
+};
+
+template<>
struct std::hash<Render_Pass> {
size_t operator()(const Render_Pass& rp) const {
return (size_t)fnv1a64((uint8_t*)&rp, sizeof rp);
@@ -717,10 +755,12 @@ struct Device_Vk : public Device {
max_vertex_formats
> vertex_formats;
Hash_Map<Shader_Id, Shader_Vk, max_shaders> shaders;
+ Hash_Map<Sampler_Id, Sampler_Vk, max_samplers> samplers;
uint32_t texture_count;
uint32_t buffer_count;
uint32_t vertex_format_count;
uint32_t shader_count;
+ uint32_t sampler_count;
Hash_Map<Render_Pass, Renderpass_Vk, max_rpos> rpo_cache;
Hash_Map<Pso_Key, Pipeline_Vk, max_pipelines> 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<uint32_t> {
struct Shader_Id : public Primitive_Id<uint32_t> {
using Primitive_Id<uint32_t>::Primitive_Id;
};
+struct Sampler_Id : public Primitive_Id<uint32_t> {
+ using Primitive_Id<uint32_t>::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