From 48e67652228406463dd262e3d434c68d5dcbf116 Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Sat, 16 Jan 2021 13:22:31 -0800 Subject: [PATCH] draw uv menu --- .gitignore | 2 + ref_vk/vk_2d.c | 77 ++++++++++++++++++++++++++--- ref_vk/vk_2d.h | 2 + ref_vk/vk_buffer.c | 49 +++++++++++++++++++ ref_vk/vk_buffer.h | 17 +++++++ ref_vk/vk_core.c | 38 ++++++++++++++- ref_vk/vk_core.h | 33 +++++++++++++ ref_vk/vk_renderstate.c | 105 +++++++++++++++++++++++++++++++++++++++- ref_vk/vk_renderstate.h | 6 +++ ref_vk/vk_rmain.c | 12 ----- 10 files changed, 320 insertions(+), 21 deletions(-) create mode 100644 ref_vk/vk_buffer.c create mode 100644 ref_vk/vk_buffer.h diff --git a/.gitignore b/.gitignore index b0c64aca..245a3bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -332,3 +332,5 @@ __pycache__ .cache compile_commands.json cscope.out + +core diff --git a/ref_vk/vk_2d.c b/ref_vk/vk_2d.c index a057b7e3..389437c1 100644 --- a/ref_vk/vk_2d.c +++ b/ref_vk/vk_2d.c @@ -1,5 +1,6 @@ #include "vk_2d.h" +#include "vk_buffer.h" #include "vk_core.h" #include "vk_common.h" #include "vk_textures.h" @@ -11,11 +12,6 @@ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, c { gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); } -void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ) -{ - gEngine.Con_Printf(S_WARN "VK FIXME: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__, - x, y, w, h, s1, t1, s2, t2, texnum, findTexture(texnum)->name); -} void R_DrawTileClear( int texnum, int x, int y, int w, int h ) { gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); @@ -34,6 +30,52 @@ typedef struct vertex_2d_s { float u, v; } vertex_2d_t; +#define MAX_PICS 1024 + +static struct { + VkPipeline pipeline; + + uint32_t max_pics, num_pics; + vk_buffer_t pics_buffer; + + // TODO texture bindings? +} g2d; + +void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ) +{ + /* gEngine.Con_Printf(S_WARN "VK FIXME: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__, */ + /* x, y, w, h, s1, t1, s2, t2, texnum, findTexture(texnum)->name); */ + + if (g2d.num_pics + 6 > g2d.max_pics) + { + //drawAccumulated(); + gEngine.Con_Printf(S_WARN "VK FIXME RAN OUT OF BUFFER: %s(%f, %f, %f, %f, %f, %f, %f, %f, %d(%s))\n", __FUNCTION__, + x, y, w, h, s1, t1, s2, t2, texnum, findTexture(texnum)->name); + return; + } + + { + vertex_2d_t *p = ((vertex_2d_t*)(g2d.pics_buffer.mapped)) + g2d.num_pics; + + const float vw = vk_core.swapchain.create_info.imageExtent.width; + const float vh = vk_core.swapchain.create_info.imageExtent.height; + const float x1 = (x / vw)*2.f - 1.f; + const float y1 = (y / vh)*2.f - 1.f; + const float x2 = ((x + w) / vw)*2.f - 1.f; + const float y2 = ((y + h) / vh)*2.f - 1.f; + + g2d.num_pics += 6; + p[0] = (vertex_2d_t){x1, y1, s1, t1}; + p[1] = (vertex_2d_t){x1, y2, s1, t2}; + p[2] = (vertex_2d_t){x2, y1, s2, t1}; + p[3] = (vertex_2d_t){x2, y1, s2, t1}; + p[4] = (vertex_2d_t){x1, y2, s1, t2}; + p[5] = (vertex_2d_t){x2, y2, s2, t2}; + + // TODO store texture + } +} + static VkPipeline createPipeline( void ) { VkVertexInputAttributeDescription attribs[] = { @@ -168,13 +210,36 @@ static VkPipeline createPipeline( void ) return pipeline; } +void vk2dBegin( void ) +{ + g2d.num_pics = 0; +} + +void vk2dEnd( void ) +{ + const VkDeviceSize offset = 0; + if (!g2d.num_pics) + return; + + vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline); + vkCmdBindVertexBuffers(vk_core.cb, 0, 1, &g2d.pics_buffer.buffer, &offset); + vkCmdDraw(vk_core.cb, g2d.num_pics, 1, 0, 0); +} + qboolean initVk2d( void ) { - VkPipeline pipeline = createPipeline(); + g2d.pipeline = createPipeline(); + + if (!createBuffer(&g2d.pics_buffer, sizeof(vertex_2d_t) * (MAX_PICS * 6), + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT )) + return false; + + g2d.max_pics = MAX_PICS * 6; return true; } void deinitVk2d( void ) { + // FIXME deinit stuff } diff --git a/ref_vk/vk_2d.h b/ref_vk/vk_2d.h index cade8c75..93472874 100644 --- a/ref_vk/vk_2d.h +++ b/ref_vk/vk_2d.h @@ -10,3 +10,5 @@ void CL_FillRGBABlend( float x, float y, float w, float h, int r, int g, int b, qboolean initVk2d( void ); void deinitVk2d( void ); +void vk2dBegin( void ); +void vk2dEnd( void ); diff --git a/ref_vk/vk_buffer.c b/ref_vk/vk_buffer.c new file mode 100644 index 00000000..ac597f32 --- /dev/null +++ b/ref_vk/vk_buffer.c @@ -0,0 +1,49 @@ +#include "vk_buffer.h" + +#include + +uint32_t findMemoryWithType(uint32_t type_index_bits, VkMemoryPropertyFlags flags) { + for (uint32_t i = 0; i < vk_core.physical_device.memory_properties.memoryTypeCount; ++i) { + if (!(type_index_bits & (1 << i))) + continue; + + if ((vk_core.physical_device.memory_properties.memoryTypes[i].propertyFlags & flags) == flags) + return i; + } + + return UINT32_MAX; +} + +qboolean createBuffer(vk_buffer_t *buf, uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags) +{ + VkBufferCreateInfo bci = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = size, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VkMemoryAllocateInfo mai = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + }; + VkMemoryRequirements memreq; + XVK_CHECK(vkCreateBuffer(vk_core.device, &bci, NULL, &buf->buffer)); + + vkGetBufferMemoryRequirements(vk_core.device, buf->buffer, &memreq); + gEngine.Con_Reportf("memreq: memoryTypeBits=0x%x alignment=%zu size=%zu", memreq.memoryTypeBits, memreq.alignment, memreq.size); + + mai.allocationSize = memreq.size; + mai.memoryTypeIndex = findMemoryWithType(memreq.memoryTypeBits, flags); + XVK_CHECK(vkAllocateMemory(vk_core.device, &mai, NULL, &buf->device_memory)); + XVK_CHECK(vkBindBufferMemory(vk_core.device, buf->buffer, buf->device_memory, 0)); + + XVK_CHECK(vkMapMemory(vk_core.device, buf->device_memory, 0, bci.size, 0, &buf->mapped)); + + return true; +} + +void destroyBuffer(vk_buffer_t *buf) { + vkUnmapMemory(vk_core.device, buf->device_memory); + vkDestroyBuffer(vk_core.device, buf->buffer, NULL); + vkFreeMemory(vk_core.device, buf->device_memory, NULL); + memset(buf, 0, sizeof(*buf)); +} diff --git a/ref_vk/vk_buffer.h b/ref_vk/vk_buffer.h new file mode 100644 index 00000000..d4c01af1 --- /dev/null +++ b/ref_vk/vk_buffer.h @@ -0,0 +1,17 @@ +#pragma once +#include "vk_core.h" + +typedef struct vk_buffer_s +{ + // TODO coalesce allocations + VkDeviceMemory device_memory; + VkBuffer buffer; + + void *mapped; + uint32_t size; +} vk_buffer_t; + +qboolean createBuffer(vk_buffer_t *buf, uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags); +void destroyBuffer(vk_buffer_t *buf); + + diff --git a/ref_vk/vk_core.c b/ref_vk/vk_core.c index 4cba37af..67b50be0 100644 --- a/ref_vk/vk_core.c +++ b/ref_vk/vk_core.c @@ -2,6 +2,7 @@ #include "vk_common.h" #include "vk_textures.h" #include "vk_2d.h" +#include "vk_renderstate.h" #include "xash3d_types.h" #include "cvardef.h" @@ -373,8 +374,8 @@ static qboolean createRenderPass( void ) { VkAttachmentDescription attachments[] = {{ .format = VK_FORMAT_B8G8R8A8_SRGB,// FIXME too early swapchain.create_info.imageFormat; .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - //.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + //.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, @@ -621,6 +622,9 @@ qboolean R_VkInit( void ) if (!initVk2d()) return false; + if (!renderstateInit()) + return false; + initTextures(); return true; @@ -628,6 +632,8 @@ qboolean R_VkInit( void ) void R_VkShutdown( void ) { + renderstateDestroy(); + deinitVk2d(); vkDestroySwapchainKHR(vk_core.device, vk_core.swapchain.swapchain, NULL); @@ -671,3 +677,31 @@ VkShaderModule loadShader(const char *filename) { Mem_Free(buf); return shader; } + +VkSemaphore createSemaphore( void ) { + VkSemaphore sema; + VkSemaphoreCreateInfo sci = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .flags = 0, + }; + XVK_CHECK(vkCreateSemaphore(vk_core.device, &sci, NULL, &sema)); + return sema; +} + +void destroySemaphore(VkSemaphore sema) { + vkDestroySemaphore(vk_core.device, sema, NULL); +} + +VkFence createFence( void ) { + VkFence fence; + VkFenceCreateInfo fci = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .flags = 0, + }; + XVK_CHECK(vkCreateFence(vk_core.device, &fci, NULL, &fence)); + return fence; +} + +void destroyFence(VkFence fence) { + vkDestroyFence(vk_core.device, fence, NULL); +} diff --git a/ref_vk/vk_core.h b/ref_vk/vk_core.h index 79b33989..c02a7606 100644 --- a/ref_vk/vk_core.h +++ b/ref_vk/vk_core.h @@ -1,4 +1,8 @@ +#pragma once +#include "vk_common.h" + #include "xash3d_types.h" +#include "com_strings.h" // S_ERROR #define VK_NO_PROTOTYPES #include @@ -8,6 +12,10 @@ void R_VkShutdown( void ); // FIXME load from embedded static structs VkShaderModule loadShader(const char *filename); +VkSemaphore createSemaphore( void ); +void destroySemaphore(VkSemaphore sema); +VkFence createFence( void ); +void destroyFence(VkFence fence); typedef struct physical_device_s { VkPhysicalDevice device; @@ -73,6 +81,31 @@ const char *resultName(VkResult result); X(vkCreateShaderModule) \ X(vkCreateCommandPool) \ X(vkAllocateCommandBuffers) \ + X(vkCreateBuffer) \ + X(vkGetBufferMemoryRequirements) \ + X(vkAllocateMemory) \ + X(vkBindBufferMemory) \ + X(vkMapMemory) \ + X(vkUnmapMemory) \ + X(vkDestroyBuffer) \ + X(vkFreeMemory) \ + X(vkAcquireNextImageKHR) \ + X(vkCmdBeginRenderPass) \ + X(vkCmdExecuteCommands) \ + X(vkCmdEndRenderPass) \ + X(vkEndCommandBuffer) \ + X(vkQueueSubmit) \ + X(vkQueuePresentKHR) \ + X(vkWaitForFences) \ + X(vkResetFences) \ + X(vkCreateSemaphore) \ + X(vkDestroySemaphore) \ + X(vkCreateFence) \ + X(vkDestroyFence) \ + X(vkBeginCommandBuffer) \ + X(vkCmdBindPipeline) \ + X(vkCmdBindVertexBuffers) \ + X(vkCmdDraw) \ #define X(f) extern PFN_##f f; DEVICE_FUNCS(X) diff --git a/ref_vk/vk_renderstate.c b/ref_vk/vk_renderstate.c index 43de91a5..02760f4a 100644 --- a/ref_vk/vk_renderstate.c +++ b/ref_vk/vk_renderstate.c @@ -1,7 +1,13 @@ +#include "vk_renderstate.h" + +#include "vk_2d.h" +#include "vk_core.h" + #include "cvardef.h" #include "const.h" #include "ref_api.h" #include "com_strings.h" +#include "eiface.h" // ARRAYSIZE extern ref_api_t gEngine; extern ref_globals_t *gpGlobals; @@ -15,6 +21,13 @@ typedef struct render_state_s { int blending_mode; // kRenderNormal, ... } render_state_t; +static struct +{ + VkSemaphore image_available; + VkSemaphore done; + VkFence fence; +} grs; + render_state_t render_state = {0}; static const char *renderModeName(int mode) @@ -38,7 +51,7 @@ void GL_SetRenderMode( int renderMode ) render_state.blending_mode = renderMode; } -void TriColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) +void TriColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) { //gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d, %d, %d, %d)\n", __FUNCTION__, (int)r, (int)g, (int)b, (int)a); @@ -56,3 +69,93 @@ void R_Set2DMode( qboolean enable ) //gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d)\n", __FUNCTION__, enable); render_state.mode_2d = enable; } + +void R_BeginFrame( qboolean clearScene ) +{ + gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d)\n", __FUNCTION__, clearScene); + vk2dBegin(); +} + +void R_RenderScene( void ) +{ + gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); +} + +void R_EndFrame( void ) +{ + //gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); + + uint32_t swapchain_image_index; + VkClearValue clear_value[] = { + {.color = {{1., 0., 0., 0.}}}, + //{.depthStencil = {1., 0.}} + }; + VkRenderPassBeginInfo rpbi = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = vk_core.render_pass, + .renderArea.extent.width = vk_core.swapchain.create_info.imageExtent.width, + .renderArea.extent.height = vk_core.swapchain.create_info.imageExtent.height, + .clearValueCount = ARRAYSIZE(clear_value), + .pClearValues = clear_value, + }; + VkPipelineStageFlags stageflags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo subinfo = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = NULL, + .commandBufferCount = 1, + .pCommandBuffers = &vk_core.cb, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &grs.image_available, + .signalSemaphoreCount = 1, + .pSignalSemaphores = &grs.done, + .pWaitDstStageMask = &stageflags, + }; + VkPresentInfoKHR presinfo = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pSwapchains = &vk_core.swapchain.swapchain, + .pImageIndices = &swapchain_image_index, + .swapchainCount = 1, + .pWaitSemaphores = &grs.done, + .waitSemaphoreCount = 1, + }; + + XVK_CHECK(vkAcquireNextImageKHR(vk_core.device, vk_core.swapchain.swapchain, UINT64_MAX, grs.image_available, + VK_NULL_HANDLE, &swapchain_image_index)); + rpbi.framebuffer = vk_core.swapchain.framebuffers[swapchain_image_index]; + + + { + VkCommandBufferBeginInfo beginfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + XVK_CHECK(vkBeginCommandBuffer(vk_core.cb, &beginfo)); + } + + vkCmdBeginRenderPass(vk_core.cb, &rpbi, VK_SUBPASS_CONTENTS_INLINE); + + vk2dEnd(); + + vkCmdEndRenderPass(vk_core.cb); + XVK_CHECK(vkEndCommandBuffer(vk_core.cb)); + + XVK_CHECK(vkQueueSubmit(vk_core.queue, 1, &subinfo, grs.fence)); + XVK_CHECK(vkQueuePresentKHR(vk_core.queue, &presinfo)); + + // TODO bad sync + XVK_CHECK(vkWaitForFences(vk_core.device, 1, &grs.fence, VK_TRUE, INT64_MAX)); + XVK_CHECK(vkResetFences(vk_core.device, 1, &grs.fence)); +} + +qboolean renderstateInit( void ) +{ + grs.image_available = createSemaphore(); + grs.done = createSemaphore(); + grs.fence = createFence(); + + return true; +} + +void renderstateDestroy( void ) +{ +} diff --git a/ref_vk/vk_renderstate.h b/ref_vk/vk_renderstate.h index a80d3869..c8ba8c02 100644 --- a/ref_vk/vk_renderstate.h +++ b/ref_vk/vk_renderstate.h @@ -6,3 +6,9 @@ void GL_SetRenderMode( int renderMode ); void TriColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); void R_AllowFog( qboolean allow ); void R_Set2DMode( qboolean enable ); +void R_BeginFrame( qboolean clearScene ); +void R_RenderScene( void ); +void R_EndFrame( void ); + +qboolean renderstateInit( void ); +void renderstateDestroy( void ); diff --git a/ref_vk/vk_rmain.c b/ref_vk/vk_rmain.c index 183b8411..d8e71bfc 100644 --- a/ref_vk/vk_rmain.c +++ b/ref_vk/vk_rmain.c @@ -38,18 +38,6 @@ void GL_ClearExtensions( void ) gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); } -void R_BeginFrame( qboolean clearScene ) -{ - gEngine.Con_Printf(S_WARN "VK FIXME: %s(%d)\n", __FUNCTION__, clearScene); -} -void R_RenderScene( void ) -{ - gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); -} -void R_EndFrame( void ) -{ - gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__); -} void R_PushScene( void ) { gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__);