Initial commit of C vulkan code
							parent
							
								
									28fc752354
								
							
						
					
					
						commit
						2accc9a952
					
				| @ -0,0 +1,55 @@ | ||||
| ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) | ||||
| CFLAGS = -I $(ROOT_DIR)/include -I/usr/local/include -O0 -g -Wall -Wextra | ||||
| LDFLAGS = -L/opt/homebrew/opt/llvm/lib -L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/lib -lglfw -lvulkan -ldl -Xlinker -rpath -Xlinker /opt/homebrew/lib | ||||
| CC = /opt/homebrew/opt/llvm/bin/clang | ||||
| CPP = /opt/homebrew/opt/llvm/bin/clang++ | ||||
| DSYM = /opt/homebrew/opt/llvm/bin/dsymutil | ||||
| GDB = /opt/homebrew/opt/llvm/bin/lldb | ||||
| 
 | ||||
| SOURCES = src/main.c src/render.c src/vma.cpp | ||||
| OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) | ||||
| VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader_src/*.vert))) | ||||
| FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader_src/*.frag))) | ||||
| 
 | ||||
| export MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=1 | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: roleplay $(VERT_SPV) $(FRAG_SPV) | ||||
| 
 | ||||
| roleplay: $(OBJECTS) | ||||
| 	$(CPP) $(CFLAGS) $(LDFLAGS) -o $@ $^ | ||||
| 
 | ||||
| %.o: %.cpp | ||||
| 	$(CPP) $(CFLAGS) -c -o $@ $< | ||||
| 
 | ||||
| %.o: %.c | ||||
| 	$(CC) $(CFLAGS) -c -o $@ $< | ||||
| 
 | ||||
| .PHONY: clean clean_compdb | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f $(FRAG_SPV) | ||||
| 	rm -f $(VERT_SPV) | ||||
| 	rm -f $(OBJECTS) | ||||
| 	rm -f roleplay | ||||
| 	rm -rf roleplay.dSYM | ||||
| 
 | ||||
| clean_compdb: | ||||
| 	rm -rf .compdb | ||||
| 	rm compile_commands.json | ||||
| 
 | ||||
| run: roleplay | ||||
| 	./roleplay | ||||
| 
 | ||||
| roleplay.dSYM: roleplay | ||||
| 	$(DSYM) roleplay | ||||
| 
 | ||||
| debug: roleplay roleplay.dSYM | ||||
| 	$(GDB) roleplay | ||||
| 
 | ||||
| 
 | ||||
| %.vert.spv: %.vert | ||||
| 	glslangValidator -V -o $@ $< | ||||
| 
 | ||||
| %.frag.spv: %.frag | ||||
| 	glslangValidator -V -o $@ $< | ||||
| @ -0,0 +1,91 @@ | ||||
| #ifndef RENDER_H | ||||
| #define RENDER_H | ||||
| 
 | ||||
| #define VK_USE_PLATFORM_MACOS_MVK | ||||
| #include "vulkan/vulkan_core.h" | ||||
| #include "vulkan/vk_enum_string_helper.h" | ||||
| 
 | ||||
| #include "vk_mem_alloc.h" | ||||
| 
 | ||||
| #define GLFW_INCLUDE_VULKAN | ||||
| #include <GLFW/glfw3.h> | ||||
| #define GLFW_EXPOSE_NATIVE_COCOA | ||||
| #include <GLFW/glfw3native.h> | ||||
| 
 | ||||
| #define GLM_FORCE_RADIANS | ||||
| #define GLM_FORCE_DEPTH_ZERO_TO_ONE | ||||
| #include <cglm/types.h> | ||||
| #include <cglm/mat4.h> | ||||
| #include <cglm/vec3.h> | ||||
| #include <cglm/affine.h> | ||||
| #include <cglm/quat.h> | ||||
| #include <cglm/cam.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| typedef struct QueueStruct { | ||||
|   VkQueue handle; | ||||
|   uint32_t family; | ||||
|   uint32_t index; | ||||
| } Queue; | ||||
| 
 | ||||
| typedef struct SwapchainDetailsStruct { | ||||
|   VkSurfaceCapabilitiesKHR capabilities; | ||||
| 
 | ||||
|   VkSurfaceFormatKHR* formats; | ||||
|   uint32_t formats_count; | ||||
| 
 | ||||
|   VkPresentModeKHR* present_modes; | ||||
|   uint32_t present_modes_count; | ||||
| } SwapchainDetails; | ||||
| 
 | ||||
| typedef struct RenderContextStruct { | ||||
|   VkInstance instance; | ||||
|   VkDebugUtilsMessengerEXT debug_messenger; | ||||
|   VkPhysicalDevice physical_device; | ||||
|   VkPhysicalDeviceMemoryProperties memories; | ||||
|   VkSurfaceKHR surface; | ||||
|   Queue graphics_queue; | ||||
|   Queue present_queue; | ||||
|   Queue transfer_queue; | ||||
|   VkDevice device; | ||||
|   VmaAllocator allocator; | ||||
| 
 | ||||
|   SwapchainDetails swapchain_details; | ||||
|   VkSurfaceFormatKHR swapchain_format; | ||||
|   VkPresentModeKHR swapchain_present_mode; | ||||
|   VkExtent2D swapchain_extent; | ||||
|   VkSwapchainKHR swapchain; | ||||
| 
 | ||||
|   uint32_t swapchain_image_count; | ||||
|   VkImage* swapchain_images; | ||||
|   VkImageView* swapchain_image_views; | ||||
|   VkFramebuffer* swapchain_framebuffers; | ||||
| 
 | ||||
|   VkFormat depth_format; | ||||
|   VkImageView depth_image_view; | ||||
|   VkImage depth_image; | ||||
|   VmaAllocation depth_image_memory; | ||||
| 
 | ||||
|   VkCommandPool extra_graphics_pool; | ||||
|   VkCommandPool graphics_pool; | ||||
|   VkCommandPool transfer_pool; | ||||
| 
 | ||||
|   VkRenderPass render_pass; | ||||
| 
 | ||||
|   VkCommandBuffer* swapchain_command_buffers; | ||||
| 
 | ||||
|   VkSemaphore* image_available_semaphores; | ||||
|   VkSemaphore* render_finished_semaphores; | ||||
| 
 | ||||
|   VkFence* in_flight_fences; | ||||
| 
 | ||||
|   VkPipeline ui_pipeline_rect; | ||||
|   VkPipeline ui_pipeline_text; | ||||
| } RenderContext; | ||||
| 
 | ||||
| GLFWwindow* init_window(); | ||||
| VkResult init_vulkan(GLFWwindow* window, RenderContext* context); | ||||
| 
 | ||||
| #endif | ||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -1,221 +0,0 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gen2brain/raylib-go/raylib" | ||||
| ) | ||||
| 
 | ||||
| type ClientAuth struct { | ||||
| 	 | ||||
| } | ||||
| 
 | ||||
| type Entity struct { | ||||
| 	 | ||||
| } | ||||
| 
 | ||||
| type LoginState int | ||||
| 
 | ||||
| const ( | ||||
| 	LOGIN_STATE_CREDENTIALS LoginState = iota | ||||
| 	LOGIN_STATE_ATTEMPTING | ||||
| 	LOGIN_STATE_ERROR | ||||
| ) | ||||
| 
 | ||||
| type ButtonState int | ||||
| 
 | ||||
| const ( | ||||
| 	BUTTON_STATE_IDLE ButtonState = iota | ||||
| 	BUTTON_STATE_HOVER | ||||
| 	BUTTON_STATE_PRESSED | ||||
| ) | ||||
| 
 | ||||
| type Scale struct { | ||||
| 	window rl.Vector2 | ||||
| 	ui uint | ||||
| } | ||||
| 
 | ||||
| type ClientState struct { | ||||
| 	auth *ClientAuth | ||||
| 	login LoginState | ||||
| 	login_button ButtonState | ||||
| 	scale Scale | ||||
| 	screen rl.Rectangle | ||||
| 	camera rl.Camera | ||||
| 
 | ||||
| 	command_queue chan interface{} | ||||
| 	network_queue chan interface{} | ||||
| 
 | ||||
| 	context *Entity | ||||
| 	context_pos rl.Vector2 | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	WIDTH  uint = 1600 | ||||
|   HEIGHT uint = 1000 | ||||
| ) | ||||
| 
 | ||||
| func scale(original rl.Rectangle, scale Scale) rl.Rectangle { | ||||
| 	return rl.Rectangle{ | ||||
| 		X: original.X, | ||||
| 		Y: original.Y, | ||||
| 		Width: original.Width*float32(scale.ui)/scale.window.X, | ||||
| 		Height: original.Height*float32(scale.ui)/scale.window.Y, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func offset(original rl.Rectangle, off_x, off_y int, scale Scale) rl.Rectangle { | ||||
| 	return rl.Rectangle{ | ||||
| 		X: original.X + float32(off_x)/scale.window.X, | ||||
| 		Y: original.Y + float32(off_y)/scale.window.Y, | ||||
| 		Width: original.Width, | ||||
| 		Height: original.Height, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func center(container, original rl.Rectangle) rl.Rectangle { | ||||
| 	return rl.Rectangle{ | ||||
| 		X: (container.Width  - original.Width )/2 + container.X, | ||||
| 		Y: (container.Height - original.Height)/2 + container.Y, | ||||
| 		Width: original.Width, | ||||
| 		Height: original.Height, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func button(rectangle rl.Rectangle, idle, hover, pressed rl.Color, text string, font_size int32, text_color rl.Color, last_state ButtonState) (action bool, next_state ButtonState) { | ||||
| 	over := rl.CheckCollisionPointRec(rl.GetMousePosition(), rectangle) | ||||
| 	action = false | ||||
| 	next_state = last_state | ||||
| 
 | ||||
| 	if(rl.IsMouseButtonPressed(rl.MouseButtonLeft) && over) { | ||||
| 		next_state = BUTTON_STATE_PRESSED | ||||
| 	} else if(rl.IsMouseButtonReleased(rl.MouseButtonLeft) && last_state == BUTTON_STATE_PRESSED) { | ||||
| 		next_state = BUTTON_STATE_IDLE | ||||
| 		if(over) { | ||||
| 			action = true | ||||
| 		} | ||||
| 	} else if(rl.IsMouseButtonUp(rl.MouseButtonLeft)) { | ||||
| 		if(last_state == BUTTON_STATE_IDLE && over) { | ||||
| 			next_state = BUTTON_STATE_HOVER | ||||
| 		} else if (last_state == BUTTON_STATE_HOVER && !over) { | ||||
| 			next_state = BUTTON_STATE_IDLE | ||||
| 		}	 | ||||
| 	} | ||||
| 	 | ||||
| 	var color rl.Color | ||||
| 	switch(next_state) { | ||||
| 	case BUTTON_STATE_HOVER: | ||||
| 		color = hover | ||||
| 	case BUTTON_STATE_PRESSED: | ||||
| 		color = pressed | ||||
| 	default: | ||||
| 		color = idle | ||||
| 	} | ||||
| 	rl.DrawRectangleRec(rectangle, color) | ||||
| 	text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, float32(font_size), 1.0) | ||||
| 	rl.DrawText(text, int32(rectangle.X + rectangle.Width/2 - text_size.X/2), int32(rectangle.Y + rectangle.Height/2 - text_size.Y/2), font_size, text_color) | ||||
| 
 | ||||
| 	return action, next_state | ||||
| } | ||||
| 
 | ||||
| func NetworkThread(network_queue chan interface{}) { | ||||
| 	for(true) { | ||||
| 		// TODO: remove
 | ||||
| 		time.Sleep(time.Millisecond) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func LogicThread(state *ClientState) { | ||||
| 	for(true) { | ||||
| 		select { | ||||
| 			case _ = <- state.command_queue: | ||||
| 			case _ = <- state.network_queue: | ||||
| 		} | ||||
| 		time.Sleep(time.Millisecond) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	state := ClientState{ | ||||
| 		auth: nil, | ||||
| 		login: LOGIN_STATE_CREDENTIALS, | ||||
| 		login_button: BUTTON_STATE_IDLE, | ||||
| 		scale: Scale{ | ||||
| 			ui: 1, | ||||
| 		}, | ||||
| 		camera: rl.NewCamera3D(rl.Vector3{}, rl.Vector3{}, rl.Vector3{}, 90, rl.CameraOrthographic), | ||||
| 		context: nil, | ||||
| 	} | ||||
| 
 | ||||
| 	go LogicThread(&state) | ||||
| 
 | ||||
| 	rl.SetConfigFlags(rl.FlagWindowHighdpi) | ||||
| 	rl.InitWindow(0, 0, "roleplay") | ||||
| 	rl.SetExitKey(0) | ||||
| 	rl.SetTargetFPS(60) | ||||
| 
 | ||||
| 	state.scale.window = rl.GetWindowScaleDPI() | ||||
| 	rl.SetWindowSize(int(float32(WIDTH)/state.scale.window.X), int(float32(HEIGHT)/state.scale.window.Y)) | ||||
| 
 | ||||
| 	state.screen.Width  = float32(WIDTH) /state.scale.window.X | ||||
| 	state.screen.Height = float32(HEIGHT)/state.scale.window.Y | ||||
| 
 | ||||
| 	for(rl.WindowShouldClose() == false) { | ||||
| 		if(state.auth == nil) { | ||||
| 			// Draw login
 | ||||
| 			rl.BeginDrawing() | ||||
| 			rl.ClearBackground(rl.Black) | ||||
| 
 | ||||
| 			logo_rect := scale(rl.Rectangle{Width: 1200, Height: 300}, state.scale) | ||||
| 			logo_rect = center(state.screen, logo_rect) | ||||
| 			logo_rect = offset(logo_rect, 0, -250, state.scale) | ||||
| 			rl.DrawRectangleRec(logo_rect, rl.Gray) | ||||
| 
 | ||||
| 			form_rect := scale(rl.Rectangle{Width: 600, Height: 400}, state.scale) | ||||
| 			form_rect = center(state.screen, form_rect) | ||||
| 			form_rect = offset(form_rect, 0, 200, state.scale) | ||||
| 			rl.DrawRectangleRec(form_rect, rl.Gray) | ||||
| 
 | ||||
| 			switch(state.login) { | ||||
| 			case LOGIN_STATE_CREDENTIALS: | ||||
| 				submit_rect := scale(rl.Rectangle{Width: 100, Height: 50}, state.scale) | ||||
| 				submit_rect = center(form_rect, submit_rect) | ||||
| 				submit_rect = offset(submit_rect, 0, 125, state.scale) | ||||
| 				var submit_action bool | ||||
| 				submit_action, state.login_button = button(submit_rect, rl.Black, rl.Brown, rl.Red, "Submit", 12, rl.White, state.login_button) | ||||
| 				if submit_action { | ||||
| 					// TODO: real auth via network thread
 | ||||
| 					state.auth = &ClientAuth{} | ||||
| 				} | ||||
| 			case LOGIN_STATE_ATTEMPTING: | ||||
| 				text := "Logging in..." | ||||
| 				text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, 20, 1.0) | ||||
| 				text_rect := center(form_rect, rl.Rectangle{Width: text_size.X, Height: text_size.Y}) | ||||
| 				rl.DrawText(text, int32(text_rect.X), int32(text_rect.Y), 20, rl.Black) | ||||
| 			case LOGIN_STATE_ERROR: | ||||
| 				text := "Error: {TODO}" | ||||
| 				text_size := rl.MeasureTextEx(rl.GetFontDefault(), text, 20, 1.0) | ||||
| 				text_rect := center(form_rect, rl.Rectangle{Width: text_size.X, Height: text_size.Y}) | ||||
| 				rl.DrawText(text, int32(text_rect.X), int32(text_rect.Y), 20, rl.Black) | ||||
| 			} | ||||
| 
 | ||||
| 			rl.EndDrawing() | ||||
| 		} else { | ||||
| 			rl.BeginDrawing() | ||||
| 			rl.ClearBackground(rl.Black) | ||||
| 			rl.BeginMode3D(state.camera) | ||||
| 
 | ||||
| 			if rl.IsMouseButtonPressed(rl.MouseButtonRight) { | ||||
| 				state.context_pos = rl.GetMousePosition() | ||||
| 				// TODO: Cast a ray into the bounding boxes
 | ||||
| 			} | ||||
| 
 | ||||
| 			if state.context != nil { | ||||
| 				 | ||||
| 			} | ||||
| 
 | ||||
| 			rl.EndMode3D() | ||||
| 			rl.EndDrawing() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,34 @@ | ||||
| #include "render.h" | ||||
| 
 | ||||
| int render_thread(GLFWwindow* window, RenderContext* render_context) { | ||||
|   while(glfwWindowShouldClose(window) == 0) { | ||||
|     glfwPollEvents(); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int logic_thread() { | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int network_thread() { | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int main() { | ||||
|   GLFWwindow* window = init_window(); | ||||
|   if(window == NULL) { | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   RenderContext render_context = {}; | ||||
|   if(init_vulkan(window, &render_context) != VK_SUCCESS) { | ||||
|     return 2; | ||||
|   } | ||||
| 
 | ||||
|   if(render_thread(window, &render_context) != 0) { | ||||
|     return 3; | ||||
|   } | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
											
												Binary file not shown.
											
										
									
								
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								
											
												Binary file not shown.
											
										
									
								| @ -0,0 +1,2 @@ | ||||
| #define VMA_IMPLEMENTATION | ||||
| #include "vk_mem_alloc.h" | ||||
											
												Binary file not shown.
											
										
									
								
		Loading…
	
		Reference in New Issue