diff --git a/src/main.cpp b/src/main.cpp index c0f914c..097c937 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,6 +39,10 @@ static SDL_GPUBuffer *tile_infos_buffer; static Sint32 window_width; static Sint32 window_height; +static Sint32 msaa_texture_width; +static Sint32 msaa_texture_height; +static SDL_GPUTexture *msaa_texture; + static bool Running = true; static M4x4 view_matrix = view (V3_(0.0f, 0.0f, 0.0f), radians(45.0f), 10.0f); @@ -661,105 +665,10 @@ static void setup_memory_functions() { static void setup_memory_functions() {} #endif -int main(int argc, char **argv) { - setup_memory_functions(); - - load_map(); - - #ifdef SDL_PLATFORM_LINUX - if (!getenv("ENABLE_VULKAN_RENDERDOC_CAPTURE")) - SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "wayland,x11"); - #endif - - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { - log_error("Failed to initialize SDL (%s). Exiting.", SDL_GetError()); - return 1; - } - - device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, true, NULL); - if (!device) { - log_error("Failed to create gpu device (%s). Exiting.", SDL_GetError()); - return 1; - } - SDL_SetGPUAllowedFramesInFlight(device, 1); - - window = SDL_CreateWindow("Mikemon", 1280, 720, SDL_WINDOW_RESIZABLE); - if (!window) { - log_error("Failed to create window (%s). Exiting.", SDL_GetError()); - return 1; - } - - if (!SDL_ClaimWindowForGPUDevice(device, window)) { - log_error("Failed to claim window for gpu device (%s). Exiting.", SDL_GetError()); - return 1; - } - SDL_SetGPUSwapchainParameters(device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR, SDL_GPU_PRESENTMODE_VSYNC); - - SDL_GPUShaderCreateInfo basic_vertex_shader_info = { - .code_size = SDL_arraysize(SPIRV_basic), - .code = SPIRV_basic, - .entrypoint = "main_vertex", - .format = SDL_GPU_SHADERFORMAT_SPIRV, - .stage = SDL_GPU_SHADERSTAGE_VERTEX, - - .num_uniform_buffers = 1, - }; - - SDL_GPUShader *basic_vertex_shader = SDL_CreateGPUShader(device, &basic_vertex_shader_info); - if (!basic_vertex_shader) { - log_error("Failed to create basic vertex shader. Exiting."); - return 1; - } - - SDL_GPUShaderCreateInfo basic_pixel_shader_info = { - .code_size = SDL_arraysize(SPIRV_basic), - .code = SPIRV_basic, - .entrypoint = "main_fragment", - .format = SDL_GPU_SHADERFORMAT_SPIRV, - .stage = SDL_GPU_SHADERSTAGE_FRAGMENT, - - .num_samplers = 1, - }; - - SDL_GPUShader *basic_pixel_shader = SDL_CreateGPUShader(device, &basic_pixel_shader_info); - if (!basic_pixel_shader) { - log_error("Failed to create basic pixel shader. Exiting."); - return 1; - } - - SDL_GPUShaderCreateInfo world_vertex_shader_info = { - .code_size = SDL_arraysize(SPIRV_world), - .code = SPIRV_world, - .entrypoint = "main_vertex", - .format = SDL_GPU_SHADERFORMAT_SPIRV, - .stage = SDL_GPU_SHADERSTAGE_VERTEX, - - .num_storage_buffers = 1, - .num_uniform_buffers = 1, - }; - - SDL_GPUShader *world_vertex_shader = SDL_CreateGPUShader(device, &world_vertex_shader_info); - if (!world_vertex_shader) { - log_error("Failed to create world vertex shader. Exiting."); - return 1; - } - - SDL_GPUShaderCreateInfo world_pixel_shader_info = { - .code_size = SDL_arraysize(SPIRV_world), - .code = SPIRV_world, - .entrypoint = "main_fragment", - .format = SDL_GPU_SHADERFORMAT_SPIRV, - .stage = SDL_GPU_SHADERSTAGE_FRAGMENT, - - .num_samplers = 1, - }; - - SDL_GPUShader *world_pixel_shader = SDL_CreateGPUShader(device, &world_pixel_shader_info); - if (!world_pixel_shader) { - log_error("Failed to create world pixel shader. Exiting."); - return 1; - } +bool enable_msaa = false; +SDL_GPUSampleCount highest_supported_sample_count = SDL_GPU_SAMPLECOUNT_1; +static bool recreate_graphics_pipelines() { SDL_GPUColorTargetDescription color_target_descriptions[] = { { .format = SDL_GetGPUSwapchainTextureFormat(device, window), @@ -772,12 +681,44 @@ int main(int argc, char **argv) { .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, .alpha_blend_op = SDL_GPU_BLENDOP_ADD, - .enable_blend = true, + .enable_blend = true, }, }, }; - { + { // basic_graphics_pipeline + SDL_GPUShaderCreateInfo basic_vertex_shader_info = { + .code_size = SDL_arraysize(SPIRV_basic), + .code = SPIRV_basic, + .entrypoint = "main_vertex", + .format = SDL_GPU_SHADERFORMAT_SPIRV, + .stage = SDL_GPU_SHADERSTAGE_VERTEX, + + .num_uniform_buffers = 1, + }; + + SDL_GPUShader *basic_vertex_shader = SDL_CreateGPUShader(device, &basic_vertex_shader_info); + if (!basic_vertex_shader) { + log_error("Failed to create basic vertex shader. Exiting."); + return false; + } + + SDL_GPUShaderCreateInfo basic_pixel_shader_info = { + .code_size = SDL_arraysize(SPIRV_basic), + .code = SPIRV_basic, + .entrypoint = "main_fragment", + .format = SDL_GPU_SHADERFORMAT_SPIRV, + .stage = SDL_GPU_SHADERSTAGE_FRAGMENT, + + .num_samplers = 1, + }; + + SDL_GPUShader *basic_pixel_shader = SDL_CreateGPUShader(device, &basic_pixel_shader_info); + if (!basic_pixel_shader) { + log_error("Failed to create basic pixel shader. Exiting."); + return false; + } + SDL_GPUVertexBufferDescription vertex_buffer_descriptions[] = { { .slot = 0, @@ -835,12 +776,20 @@ int main(int argc, char **argv) { .front_face = SDL_GPU_FRONTFACE_CLOCKWISE, .enable_depth_clip = true, }, + .multisample_state = { + .sample_count = enable_msaa ? highest_supported_sample_count : SDL_GPU_SAMPLECOUNT_1, + }, .target_info = { .color_target_descriptions = color_target_descriptions, .num_color_targets = SDL_arraysize(color_target_descriptions), }, }; + if (basic_graphics_pipeline) { + SDL_ReleaseGPUGraphicsPipeline(device, basic_graphics_pipeline); + basic_graphics_pipeline = NULL; + } + basic_graphics_pipeline = SDL_CreateGPUGraphicsPipeline(device, &basic_graphics_pipeline_info); if (!basic_graphics_pipeline) { log_error("Failed to create basic graphics pipeline. Exiting."); @@ -851,7 +800,40 @@ int main(int argc, char **argv) { SDL_ReleaseGPUShader(device, basic_pixel_shader); } - { + { // world_graphics_pipeline + SDL_GPUShaderCreateInfo world_vertex_shader_info = { + .code_size = SDL_arraysize(SPIRV_world), + .code = SPIRV_world, + .entrypoint = "main_vertex", + .format = SDL_GPU_SHADERFORMAT_SPIRV, + .stage = SDL_GPU_SHADERSTAGE_VERTEX, + + .num_storage_buffers = 1, + .num_uniform_buffers = 1, + }; + + SDL_GPUShader *world_vertex_shader = SDL_CreateGPUShader(device, &world_vertex_shader_info); + if (!world_vertex_shader) { + log_error("Failed to create world vertex shader. Exiting."); + return false; + } + + SDL_GPUShaderCreateInfo world_pixel_shader_info = { + .code_size = SDL_arraysize(SPIRV_world), + .code = SPIRV_world, + .entrypoint = "main_fragment", + .format = SDL_GPU_SHADERFORMAT_SPIRV, + .stage = SDL_GPU_SHADERSTAGE_FRAGMENT, + + .num_samplers = 1, + }; + + SDL_GPUShader *world_pixel_shader = SDL_CreateGPUShader(device, &world_pixel_shader_info); + if (!world_pixel_shader) { + log_error("Failed to create world pixel shader. Exiting."); + return false; + } + SDL_GPUVertexBufferDescription vertex_buffer_descriptions[] = { { .slot = 0, @@ -897,12 +879,20 @@ int main(int argc, char **argv) { .front_face = SDL_GPU_FRONTFACE_CLOCKWISE, .enable_depth_clip = true, }, + .multisample_state = { + .sample_count = enable_msaa ? highest_supported_sample_count : SDL_GPU_SAMPLECOUNT_1, + }, .target_info = { .color_target_descriptions = color_target_descriptions, .num_color_targets = SDL_arraysize(color_target_descriptions), }, }; + if (world_graphics_pipeline) { + SDL_ReleaseGPUGraphicsPipeline(device, world_graphics_pipeline); + world_graphics_pipeline = NULL; + } + world_graphics_pipeline = SDL_CreateGPUGraphicsPipeline(device, &world_graphics_pipeline_info); if (!world_graphics_pipeline) { log_error("Failed to create world graphics pipeline. Exiting."); @@ -913,6 +903,50 @@ int main(int argc, char **argv) { SDL_ReleaseGPUShader(device, world_pixel_shader); } + return true; +} + +int main(int argc, char **argv) { + setup_memory_functions(); + + load_map(); + + #ifdef SDL_PLATFORM_LINUX + if (!getenv("ENABLE_VULKAN_RENDERDOC_CAPTURE")) + SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "wayland,x11"); + #endif + + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { + log_error("Failed to initialize SDL (%s). Exiting.", SDL_GetError()); + return 1; + } + + device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, true, NULL); + if (!device) { + log_error("Failed to create gpu device (%s). Exiting.", SDL_GetError()); + return 1; + } + SDL_SetGPUAllowedFramesInFlight(device, 1); + + window = SDL_CreateWindow("Mikemon", 1280, 720, SDL_WINDOW_RESIZABLE); + if (!window) { + log_error("Failed to create window (%s). Exiting.", SDL_GetError()); + return 1; + } + + if (!SDL_ClaimWindowForGPUDevice(device, window)) { + log_error("Failed to claim window for gpu device (%s). Exiting.", SDL_GetError()); + return 1; + } + SDL_SetGPUSwapchainParameters(device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR, SDL_GPU_PRESENTMODE_VSYNC); + + SDL_GPUTextureFormat swapchain_format = SDL_GetGPUSwapchainTextureFormat(device, window); + highest_supported_sample_count = SDL_GPUTextureSupportsSampleCount(device, swapchain_format, SDL_GPU_SAMPLECOUNT_2) ? SDL_GPU_SAMPLECOUNT_2 : highest_supported_sample_count; + highest_supported_sample_count = SDL_GPUTextureSupportsSampleCount(device, swapchain_format, SDL_GPU_SAMPLECOUNT_4) ? SDL_GPU_SAMPLECOUNT_4 : highest_supported_sample_count; + highest_supported_sample_count = SDL_GPUTextureSupportsSampleCount(device, swapchain_format, SDL_GPU_SAMPLECOUNT_8) ? SDL_GPU_SAMPLECOUNT_8 : highest_supported_sample_count; + + recreate_graphics_pipelines(); + SDL_GPUTexture *player_texture = create_shader_texture("../assets/decorations/strawberry.png"); if (!player_texture) { log_error("Failed to create shader texture. Exiting."); @@ -1115,6 +1149,14 @@ int main(int argc, char **argv) { ImGui::DragFloat("fovy", &per_frame.fovy_degrees); ImGui::DragFloat("camera_distance", &per_frame.camera_distance, 0.25f, 1.0f, INFINITY); ImGui::DragFloat("camera_tilt", &per_frame.camera_tilt, 0.25f, 0.0f, 89.0f); + + if (ImGui::Checkbox("MSAA", &enable_msaa)) { + recreate_graphics_pipelines(); + if (msaa_texture) { + SDL_ReleaseGPUTexture(device, msaa_texture); + msaa_texture = NULL; + } + } } ImGui::End(); @@ -1276,6 +1318,33 @@ int main(int argc, char **argv) { ImDrawData *draw_data = ImGui::GetDrawData(); continue; } + + if (enable_msaa && (!msaa_texture || msaa_texture_width != width || msaa_texture_height != height)) { + if (msaa_texture) { + SDL_ReleaseGPUTexture(device, msaa_texture); + msaa_texture = NULL; + } + + SDL_GPUTextureCreateInfo texture_info = { + .type = SDL_GPU_TEXTURETYPE_2D, + .format = swapchain_format, + .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET, + .width = (Uint32)width, + .height = (Uint32)height, + + .layer_count_or_depth = 1, + .num_levels = 1, + .sample_count = highest_supported_sample_count, + }; + + msaa_texture = SDL_CreateGPUTexture(device, &texture_info); + if (!msaa_texture) { + log_error("Failed to create gpu texture (%s).", SDL_GetError()); + return 1; + } + msaa_texture_width = width; + msaa_texture_height = height; + } { ZoneScopedN("Update"); @@ -1308,10 +1377,12 @@ int main(int argc, char **argv) { } SDL_GPUColorTargetInfo color_target_info = { - .texture = swapchain_texture, - .clear_color = { .r = 1.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f }, - .load_op = SDL_GPU_LOADOP_CLEAR, - .store_op = SDL_GPU_STOREOP_STORE, + .texture = enable_msaa ? msaa_texture : swapchain_texture, + .clear_color = { .r = 1.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f }, + .load_op = SDL_GPU_LOADOP_CLEAR, + .store_op = enable_msaa ? SDL_GPU_STOREOP_RESOLVE : SDL_GPU_STOREOP_STORE, + .resolve_texture = swapchain_texture, + .cycle = true, }; SDL_GPURenderPass *render_pass = SDL_BeginGPURenderPass(command_buffer, &color_target_info, 1, NULL);