diff --git a/CMakeLists.txt b/CMakeLists.txt index 158ae9c..2c2d91e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,7 +192,7 @@ else(NOT GEKKO) endif() include_directories(${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) - list(APPEND _BOO_SYS_LIBS X11 Xi GL asound ${DBUS_LIBRARY} pthread) + list(APPEND _BOO_SYS_LIBS X11 Xi Xrandr GL asound ${DBUS_LIBRARY} pthread) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") message(STATUS "Enabling Vulkan support") diff --git a/lib/graphicsdev/Common.hpp b/lib/graphicsdev/Common.hpp index 52f8739..67d6d2b 100644 --- a/lib/graphicsdev/Common.hpp +++ b/lib/graphicsdev/Common.hpp @@ -95,6 +95,7 @@ public: { m_parent = other.m_parent; other.m_parent = nullptr; return *this; } Token(Token&& other) { m_parent = other.m_parent; other.m_parent = nullptr; } + void reset() { if (m_parent) m_parent->decrement(); m_parent = nullptr; } ~Token() { if (m_parent) m_parent->decrement(); } operator bool() const { return m_parent != nullptr; } ShaderImpl& get() const { return static_cast(*m_parent); } diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 19eceba..074917b 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -67,6 +67,7 @@ public: ThreadLocalPtr GLDataFactoryImpl::m_deferredData; struct GLData : IGraphicsDataPriv { + int m_deadCounter = 0; std::vector> m_SPs; std::vector> m_SBinds; std::vector> m_SBufs; @@ -85,6 +86,7 @@ struct GLPoolItem : IGraphicsDataPriv struct GLPool : IGraphicsBufferPool { + int m_deadCounter = 0; std::unordered_set m_items; ~GLPool() { @@ -450,9 +452,9 @@ class GLShaderPipeline : public IShaderPipeline friend class GLDataFactory; friend struct GLCommandQueue; friend struct GLShaderDataBinding; - GLShareableShader::Token m_vert; - GLShareableShader::Token m_frag; - GLuint m_prog = 0; + mutable GLShareableShader::Token m_vert; + mutable GLShareableShader::Token m_frag; + mutable GLuint m_prog = 0; GLenum m_sfactor = GL_ONE; GLenum m_dfactor = GL_ZERO; GLenum m_drawPrim = GL_TRIANGLES; @@ -462,10 +464,11 @@ class GLShaderPipeline : public IShaderPipeline bool m_alphaWrite = true; bool m_subtractBlend = false; CullMode m_culling; - std::vector m_uniLocs; + mutable std::vector m_uniLocs; + mutable std::vector m_texNames; + mutable std::vector m_blockNames; GLShaderPipeline(GLData* parent) : IShaderPipeline(parent) {} public: - operator bool() const {return m_prog != 0;} ~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); } GLShaderPipeline& operator=(const GLShaderPipeline&) = delete; GLShaderPipeline(const GLShaderPipeline&) = delete; @@ -485,6 +488,8 @@ public: m_subtractBlend = other.m_subtractBlend; m_culling = other.m_culling; m_uniLocs = std::move(other.m_uniLocs); + m_texNames = std::move(other.m_texNames); + m_blockNames = std::move(other.m_blockNames); return *this; } GLShaderPipeline(GLShaderPipeline&& other) @@ -492,7 +497,71 @@ public: GLuint bind() const { - glUseProgram(m_prog); + if (!m_prog) + { + m_prog = glCreateProgram(); + if (!m_prog) + { + Log.report(logvisor::Error, "unable to create shader program"); + return 0; + } + + glAttachShader(m_prog, m_vert.get().m_shader); + glAttachShader(m_prog, m_frag.get().m_shader); + + glLinkProgram(m_prog); + + glDetachShader(m_prog, m_vert.get().m_shader); + glDetachShader(m_prog, m_frag.get().m_shader); + + m_vert.reset(); + m_frag.reset(); + + GLint status; + glGetProgramiv(m_prog, GL_LINK_STATUS, &status); + if (status != GL_TRUE) + { + GLint logLen; + glGetProgramiv(m_prog, GL_INFO_LOG_LENGTH, &logLen); + char* log = (char*)malloc(logLen); + glGetProgramInfoLog(m_prog, logLen, nullptr, log); + Log.report(logvisor::Error, "unable to link shader program\n%s\n", log); + free(log); + return 0; + } + + glUseProgram(m_prog); + + if (m_blockNames.size()) + { + m_uniLocs.reserve(m_blockNames.size()); + for (size_t i=0 ; i(); + } + + if (m_texNames.size()) + { + for (int i=0 ; i(); + } + } + else + { + glUseProgram(m_prog); + } if (m_dfactor != GL_ZERO) { @@ -654,54 +723,13 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline shader.m_frag = it->second->lock(); } - shader.m_prog = glCreateProgram(); - if (!shader.m_prog) - { - Log.report(logvisor::Error, "unable to create shader program"); - return nullptr; - } + shader.m_texNames.reserve(texCount); + for (int i=0 ; i lk(m_committedMutex); GLData* data = static_cast(d); - m_committedData.erase(data); - data->decrement(); + data->m_deadCounter = 3; + //m_committedData.erase(data); + //data->decrement(); } void GLDataFactoryImpl::destroyAllData() @@ -945,8 +974,9 @@ void GLDataFactoryImpl::destroyPool(IGraphicsBufferPool* p) { std::unique_lock lk(m_committedMutex); GLPool* pool = static_cast(p); - m_committedPools.erase(pool); - delete pool; + pool->m_deadCounter = 3; + //m_committedPools.erase(pool); + //delete pool; } IGraphicsBufferD* GLDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, @@ -1094,9 +1124,9 @@ struct GLCommandQueue : IGraphicsCommandQueue std::vector> m_pendingPosts1; std::vector> m_pendingPosts2; std::vector m_pendingFmtAdds; - std::vector> m_pendingFmtDels; + //std::vector> m_pendingFmtDels; std::vector m_pendingFboAdds; - std::vector m_pendingFboDels; + //std::vector m_pendingFboDels; static void ConfigureVertexFormat(GLVertexFormat* fmt) { @@ -1213,6 +1243,7 @@ struct GLCommandQueue : IGraphicsCommandQueue self->m_pendingFmtAdds.clear(); } +#if 0 if (self->m_pendingFmtDels.size()) { for (const auto& fmt : self->m_pendingFmtDels) @@ -1226,12 +1257,14 @@ struct GLCommandQueue : IGraphicsCommandQueue glDeleteFramebuffers(1, &fbo); self->m_pendingFboDels.clear(); } +#endif if (self->m_pendingPosts2.size()) posts.swap(self->m_pendingPosts2); } std::vector& cmds = self->m_cmdBufs[self->m_drawBuf]; GLenum currentPrim = GL_TRIANGLES; + const GLShaderDataBinding* curBinding = nullptr; for (const Command& cmd : cmds) { switch (cmd.m_op) @@ -1240,6 +1273,7 @@ struct GLCommandQueue : IGraphicsCommandQueue { const GLShaderDataBinding* binding = static_cast(cmd.binding); binding->bind(self->m_drawBuf); + curBinding = binding; currentPrim = binding->m_pipeline->m_drawPrim; break; } @@ -1332,6 +1366,31 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.clear(); for (auto& p : posts) p(); + + GLDataFactoryImpl* gfxF = static_cast(self->m_parent->getDataFactory()); + std::unique_lock datalk(gfxF->m_committedMutex); + for (auto it = gfxF->m_committedData.begin() ; it != gfxF->m_committedData.end() ;) + { + GLData* d = *it; + if (d->m_deadCounter && --d->m_deadCounter == 0) + { + d->decrement(); + it = gfxF->m_committedData.erase(it); + continue; + } + ++it; + } + for (auto it = gfxF->m_committedPools.begin() ; it != gfxF->m_committedPools.end() ;) + { + GLPool* p = *it; + if (p->m_deadCounter && --p->m_deadCounter == 0) + { + delete p; + it = gfxF->m_committedPools.erase(it); + continue; + } + ++it; + } } } @@ -1496,6 +1555,7 @@ struct GLCommandQueue : IGraphicsCommandQueue void delVertexFormat(GLVertexFormat* fmt) { +#if 0 std::unique_lock lk(m_mt); bool foundAdd = false; for (GLVertexFormat*& afmt : m_pendingFmtAdds) @@ -1507,6 +1567,8 @@ struct GLCommandQueue : IGraphicsCommandQueue } if (!foundAdd) m_pendingFmtDels.push_back({fmt->m_vao[0], fmt->m_vao[1], fmt->m_vao[2]}); +#endif + glDeleteVertexArrays(3, fmt->m_vao); } void addFBO(GLTextureR* tex) @@ -1517,8 +1579,11 @@ struct GLCommandQueue : IGraphicsCommandQueue void delFBO(GLTextureR* tex) { +#if 0 std::unique_lock lk(m_mt); m_pendingFboDels.push_back(tex->m_fbo); +#endif + glDeleteFramebuffers(1, &tex->m_fbo); } void execute() diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 90d41f6..9aa75ec 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -26,11 +26,10 @@ class VulkanDataFactoryImpl; struct VulkanShareableShader : IShareableShader { VkDevice m_dev; - VkShaderModule m_shader; + std::vector m_shader; VulkanShareableShader(VulkanDataFactoryImpl& fac, uint64_t srcKey, uint64_t binKey, - VkDevice dev, VkShaderModule s) + VkDevice dev, const std::vector& s) : IShareableShader(fac, srcKey, binKey), m_dev(dev), m_shader(s) {} - ~VulkanShareableShader() { vk::DestroyShaderModule(m_dev, m_shader, nullptr); } }; class VulkanDataFactoryImpl : public VulkanDataFactory @@ -338,8 +337,8 @@ void VulkanContext::initVulkan(const char* appName) #ifndef NDEBUG m_layerNames.push_back("VK_LAYER_LUNARG_core_validation"); m_layerNames.push_back("VK_LAYER_LUNARG_object_tracker"); - m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation"); - m_layerNames.push_back("VK_LAYER_GOOGLE_threading"); + //m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation"); + //m_layerNames.push_back("VK_LAYER_GOOGLE_threading"); #endif demo_check_layers(m_instanceLayerProperties, m_layerNames); @@ -753,7 +752,7 @@ struct VulkanData : IGraphicsDataPriv std::vector> m_DTexs; std::vector> m_RTexs; std::vector> m_VFmts; - bool m_dead = false; + int m_deadCounter = 0; VulkanData(VulkanContext* ctx) : m_ctx(ctx) {} ~VulkanData() { @@ -769,7 +768,7 @@ struct VulkanPoolItem : IGraphicsDataPriv VulkanContext* m_ctx; VkDeviceMemory m_bufMem = VK_NULL_HANDLE; std::unique_ptr m_buf; - bool m_dead = false; + int m_deadCounter = 0; VulkanPoolItem(VulkanContext* ctx) : m_ctx(ctx) {} ~VulkanPoolItem() { @@ -781,7 +780,7 @@ struct VulkanPoolItem : IGraphicsDataPriv struct VulkanPool : IGraphicsBufferPool { std::unordered_set m_items; - bool m_dead = false; + int m_deadCounter = 0; ~VulkanPool() { for (auto& item : m_items) @@ -792,7 +791,7 @@ struct VulkanPool : IGraphicsBufferPool { for (auto it = m_items.begin() ; it != m_items.end() ;) { - if ((*it)->m_dead) + if ((*it)->m_deadCounter && --(*it)->m_deadCounter == 0) { (*it)->decrement(); it = m_items.erase(it); @@ -1881,8 +1880,18 @@ class VulkanShaderPipeline : public IShaderPipeline VulkanContext* m_ctx; VkPipelineCache m_pipelineCache; const VulkanVertexFormat* m_vtxFmt; - VulkanShareableShader::Token m_vert; - VulkanShareableShader::Token m_frag; + mutable VulkanShareableShader::Token m_vert; + mutable VulkanShareableShader::Token m_frag; + BlendFactor m_srcFac; + BlendFactor m_dstFac; + Primitive m_prim; + ZTest m_depthTest; + bool m_depthWrite; + bool m_colorWrite; + bool m_alphaWrite; + CullMode m_culling; + mutable VkPipeline m_pipeline = VK_NULL_HANDLE; + VulkanShaderPipeline(IGraphicsData* parent, VulkanContext* ctx, VulkanShareableShader::Token&& vert, @@ -1893,171 +1902,197 @@ class VulkanShaderPipeline : public IShaderPipeline ZTest depthTest, bool depthWrite, bool colorWrite, bool alphaWrite, CullMode culling) : IShaderPipeline(parent), m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), - m_vert(std::move(vert)), m_frag(std::move(frag)) - { - VkCullModeFlagBits cullMode; - switch (culling) - { - case CullMode::None: - default: - cullMode = VK_CULL_MODE_NONE; - break; - case CullMode::Backface: - cullMode = VK_CULL_MODE_BACK_BIT; - break; - case CullMode::Frontface: - cullMode = VK_CULL_MODE_FRONT_BIT; - break; - } - - VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {}; - VkPipelineDynamicStateCreateInfo dynamicState = {}; - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicState.pNext = nullptr; - dynamicState.pDynamicStates = dynamicStateEnables; - dynamicState.dynamicStateCount = 0; - - VkPipelineShaderStageCreateInfo stages[2] = {}; - - stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[0].pNext = nullptr; - stages[0].flags = 0; - stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - stages[0].module = m_vert.get().m_shader; - stages[0].pName = "main"; - stages[0].pSpecializationInfo = nullptr; - - stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[1].pNext = nullptr; - stages[1].flags = 0; - stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stages[1].module = m_frag.get().m_shader; - stages[1].pName = "main"; - stages[1].pSpecializationInfo = nullptr; - - VkPipelineInputAssemblyStateCreateInfo assemblyInfo = {}; - assemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - assemblyInfo.pNext = nullptr; - assemblyInfo.flags = 0; - assemblyInfo.topology = PRIMITIVE_TABLE[int(prim)]; - assemblyInfo.primitiveRestartEnable = VK_FALSE; - - VkPipelineViewportStateCreateInfo viewportInfo = {}; - viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportInfo.pNext = nullptr; - viewportInfo.flags = 0; - viewportInfo.viewportCount = 1; - viewportInfo.pViewports = nullptr; - viewportInfo.scissorCount = 1; - viewportInfo.pScissors = nullptr; - dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; - dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; - - VkPipelineRasterizationStateCreateInfo rasterizationInfo = {}; - rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizationInfo.pNext = nullptr; - rasterizationInfo.flags = 0; - rasterizationInfo.depthClampEnable = VK_FALSE; - rasterizationInfo.rasterizerDiscardEnable = VK_FALSE; - rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationInfo.cullMode = cullMode; - rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterizationInfo.depthBiasEnable = VK_FALSE; - rasterizationInfo.lineWidth = 1.f; - - VkPipelineMultisampleStateCreateInfo multisampleInfo = {}; - multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampleInfo.pNext = nullptr; - multisampleInfo.flags = 0; - multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineDepthStencilStateCreateInfo depthStencilInfo = {}; - depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencilInfo.pNext = nullptr; - depthStencilInfo.flags = 0; - depthStencilInfo.depthTestEnable = depthTest != ZTest::None; - depthStencilInfo.depthWriteEnable = depthWrite; - depthStencilInfo.front.compareOp = VK_COMPARE_OP_ALWAYS; - depthStencilInfo.back.compareOp = VK_COMPARE_OP_ALWAYS; - - switch (depthTest) - { - case ZTest::None: - default: - depthStencilInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS; - break; - case ZTest::LEqual: - depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - break; - case ZTest::Greater: - depthStencilInfo.depthCompareOp = VK_COMPARE_OP_GREATER; - break; - case ZTest::Equal: - depthStencilInfo.depthCompareOp = VK_COMPARE_OP_EQUAL; - break; - } - - VkPipelineColorBlendAttachmentState colorAttachment = {}; - colorAttachment.blendEnable = dstFac != BlendFactor::Zero; - if (srcFac == BlendFactor::Subtract || dstFac == BlendFactor::Subtract) - { - colorAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR; - colorAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; - colorAttachment.colorBlendOp = VK_BLEND_OP_SUBTRACT; - } - else - { - colorAttachment.srcColorBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; - colorAttachment.dstColorBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)]; - colorAttachment.colorBlendOp = VK_BLEND_OP_ADD; - } - colorAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - colorAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - colorAttachment.colorWriteMask = - (colorWrite ? (VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT) : 0) | - (alphaWrite ? VK_COLOR_COMPONENT_A_BIT : 0); - - VkPipelineColorBlendStateCreateInfo colorBlendInfo = {}; - colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlendInfo.pNext = nullptr; - colorBlendInfo.flags = 0; - colorBlendInfo.logicOpEnable = VK_FALSE; - colorBlendInfo.attachmentCount = 1; - colorBlendInfo.pAttachments = &colorAttachment; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = {}; - pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineCreateInfo.pNext = nullptr; - pipelineCreateInfo.flags = 0; - pipelineCreateInfo.stageCount = 2; - pipelineCreateInfo.pStages = stages; - pipelineCreateInfo.pVertexInputState = &vtxFmt->m_info; - pipelineCreateInfo.pInputAssemblyState = &assemblyInfo; - pipelineCreateInfo.pViewportState = &viewportInfo; - pipelineCreateInfo.pRasterizationState = &rasterizationInfo; - pipelineCreateInfo.pMultisampleState = &multisampleInfo; - pipelineCreateInfo.pDepthStencilState = &depthStencilInfo; - pipelineCreateInfo.pColorBlendState = &colorBlendInfo; - pipelineCreateInfo.pDynamicState = &dynamicState; - pipelineCreateInfo.layout = ctx->m_pipelinelayout; - pipelineCreateInfo.renderPass = ctx->m_pass; - - ThrowIfFailed(vk::CreateGraphicsPipelines(ctx->m_dev, pipelineCache, 1, &pipelineCreateInfo, - nullptr, &m_pipeline)); - } + m_vert(std::move(vert)), m_frag(std::move(frag)), m_srcFac(srcFac), m_dstFac(dstFac), + m_prim(prim), m_depthTest(depthTest), m_depthWrite(depthWrite), m_colorWrite(colorWrite), + m_alphaWrite(alphaWrite), m_culling(culling) + {} public: - VkPipeline m_pipeline; ~VulkanShaderPipeline() { - vk::DestroyPipeline(m_ctx->m_dev, m_pipeline, nullptr); + if (m_pipeline) + vk::DestroyPipeline(m_ctx->m_dev, m_pipeline, nullptr); if (m_pipelineCache) vk::DestroyPipelineCache(m_ctx->m_dev, m_pipelineCache, nullptr); } VulkanShaderPipeline& operator=(const VulkanShaderPipeline&) = delete; VulkanShaderPipeline(const VulkanShaderPipeline&) = delete; + VkPipeline bind() const + { + if (!m_pipeline) + { + VkCullModeFlagBits cullMode; + switch (m_culling) + { + case CullMode::None: + default: + cullMode = VK_CULL_MODE_NONE; + break; + case CullMode::Backface: + cullMode = VK_CULL_MODE_BACK_BIT; + break; + case CullMode::Frontface: + cullMode = VK_CULL_MODE_FRONT_BIT; + break; + } + + VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {}; + VkPipelineDynamicStateCreateInfo dynamicState = {}; + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.pNext = nullptr; + dynamicState.pDynamicStates = dynamicStateEnables; + dynamicState.dynamicStateCount = 0; + + VkPipelineShaderStageCreateInfo stages[2] = {}; + + VkShaderModuleCreateInfo smCreateInfo = {}; + smCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + VkShaderModule vertModule, fragModule; + const auto& vertShader = m_vert.get().m_shader; + smCreateInfo.codeSize = vertShader.size() * sizeof(unsigned int); + smCreateInfo.pCode = vertShader.data(); + ThrowIfFailed(vk::CreateShaderModule(m_ctx->m_dev, &smCreateInfo, nullptr, &vertModule)); + const auto& fragShader = m_frag.get().m_shader; + smCreateInfo.codeSize = fragShader.size() * sizeof(unsigned int); + smCreateInfo.pCode = fragShader.data(); + ThrowIfFailed(vk::CreateShaderModule(m_ctx->m_dev, &smCreateInfo, nullptr, &fragModule)); + + stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[0].pNext = nullptr; + stages[0].flags = 0; + stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stages[0].module = vertModule; + stages[0].pName = "main"; + stages[0].pSpecializationInfo = nullptr; + + stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[1].pNext = nullptr; + stages[1].flags = 0; + stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stages[1].module = fragModule; + stages[1].pName = "main"; + stages[1].pSpecializationInfo = nullptr; + + VkPipelineInputAssemblyStateCreateInfo assemblyInfo = {}; + assemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + assemblyInfo.pNext = nullptr; + assemblyInfo.flags = 0; + assemblyInfo.topology = PRIMITIVE_TABLE[int(m_prim)]; + assemblyInfo.primitiveRestartEnable = VK_FALSE; + + VkPipelineViewportStateCreateInfo viewportInfo = {}; + viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportInfo.pNext = nullptr; + viewportInfo.flags = 0; + viewportInfo.viewportCount = 1; + viewportInfo.pViewports = nullptr; + viewportInfo.scissorCount = 1; + viewportInfo.pScissors = nullptr; + dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; + dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; + + VkPipelineRasterizationStateCreateInfo rasterizationInfo = {}; + rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizationInfo.pNext = nullptr; + rasterizationInfo.flags = 0; + rasterizationInfo.depthClampEnable = VK_FALSE; + rasterizationInfo.rasterizerDiscardEnable = VK_FALSE; + rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL; + rasterizationInfo.cullMode = cullMode; + rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizationInfo.depthBiasEnable = VK_FALSE; + rasterizationInfo.lineWidth = 1.f; + + VkPipelineMultisampleStateCreateInfo multisampleInfo = {}; + multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampleInfo.pNext = nullptr; + multisampleInfo.flags = 0; + multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineDepthStencilStateCreateInfo depthStencilInfo = {}; + depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencilInfo.pNext = nullptr; + depthStencilInfo.flags = 0; + depthStencilInfo.depthTestEnable = m_depthTest != ZTest::None; + depthStencilInfo.depthWriteEnable = m_depthWrite; + depthStencilInfo.front.compareOp = VK_COMPARE_OP_ALWAYS; + depthStencilInfo.back.compareOp = VK_COMPARE_OP_ALWAYS; + + switch (m_depthTest) + { + case ZTest::None: + default: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS; + break; + case ZTest::LEqual: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + break; + case ZTest::Greater: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_GREATER; + break; + case ZTest::Equal: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_EQUAL; + break; + } + + VkPipelineColorBlendAttachmentState colorAttachment = {}; + colorAttachment.blendEnable = m_dstFac != BlendFactor::Zero; + if (m_srcFac == BlendFactor::Subtract || m_dstFac == BlendFactor::Subtract) + { + colorAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR; + colorAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; + colorAttachment.colorBlendOp = VK_BLEND_OP_SUBTRACT; + } + else + { + colorAttachment.srcColorBlendFactor = BLEND_FACTOR_TABLE[int(m_srcFac)]; + colorAttachment.dstColorBlendFactor = BLEND_FACTOR_TABLE[int(m_dstFac)]; + colorAttachment.colorBlendOp = VK_BLEND_OP_ADD; + } + colorAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + colorAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + colorAttachment.colorWriteMask = + (m_colorWrite ? (VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT) : 0) | + (m_alphaWrite ? VK_COLOR_COMPONENT_A_BIT : 0); + + VkPipelineColorBlendStateCreateInfo colorBlendInfo = {}; + colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlendInfo.pNext = nullptr; + colorBlendInfo.flags = 0; + colorBlendInfo.logicOpEnable = VK_FALSE; + colorBlendInfo.attachmentCount = 1; + colorBlendInfo.pAttachments = &colorAttachment; + + VkGraphicsPipelineCreateInfo pipelineCreateInfo = {}; + pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineCreateInfo.pNext = nullptr; + pipelineCreateInfo.flags = 0; + pipelineCreateInfo.stageCount = 2; + pipelineCreateInfo.pStages = stages; + pipelineCreateInfo.pVertexInputState = &m_vtxFmt->m_info; + pipelineCreateInfo.pInputAssemblyState = &assemblyInfo; + pipelineCreateInfo.pViewportState = &viewportInfo; + pipelineCreateInfo.pRasterizationState = &rasterizationInfo; + pipelineCreateInfo.pMultisampleState = &multisampleInfo; + pipelineCreateInfo.pDepthStencilState = &depthStencilInfo; + pipelineCreateInfo.pColorBlendState = &colorBlendInfo; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.layout = m_ctx->m_pipelinelayout; + pipelineCreateInfo.renderPass = m_ctx->m_pass; + + ThrowIfFailed(vk::CreateGraphicsPipelines(m_ctx->m_dev, m_pipelineCache, 1, &pipelineCreateInfo, + nullptr, &m_pipeline)); + + vk::DestroyShaderModule(m_ctx->m_dev, vertModule, nullptr); + vk::DestroyShaderModule(m_ctx->m_dev, fragModule, nullptr); + + m_vert.reset(); + m_frag.reset(); + } + return m_pipeline; + } }; static VkDeviceSize SizeBufferForGPU(IGraphicsBuffer* buf, VulkanContext* ctx, @@ -2156,7 +2191,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv std::unique_ptr m_ubufs; std::vector> m_ubufOffs; size_t m_texCount; - VkImageView m_knownViewHandles[2][8] = {}; + VkImageView m_knownViewHandles[2][BOO_GLSL_MAX_TEXTURE_COUNT] = {}; struct BindTex { ITexture* tex; @@ -2402,7 +2437,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv if (totalWrites) vk::UpdateDescriptorSets(m_ctx->m_dev, totalWrites, writes, 0, nullptr); - vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->m_pipeline); + vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->bind()); if (m_descSets[b]) vk::CmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_ctx->m_pipelinelayout, 0, 1, &m_descSets[b], 0, nullptr); @@ -3023,13 +3058,13 @@ void VulkanTextureD::unmap() void VulkanDataFactoryImpl::destroyData(IGraphicsData* d) { VulkanData* data = static_cast(d); - data->m_dead = true; + data->m_deadCounter = 3; } void VulkanDataFactoryImpl::destroyPool(IGraphicsBufferPool* p) { VulkanPool* pool = static_cast(p); - pool->m_dead = true; + pool->m_deadCounter = 3; } void VulkanDataFactoryImpl::destroyAllData() @@ -3255,15 +3290,10 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline binHashes[0] = CompileVert(vertBlob, vertSource, srcHashes[0], factory); } - smCreateInfo.codeSize = useVertBlob->size() * sizeof(unsigned int); - smCreateInfo.pCode = useVertBlob->data(); - VkShaderModule vertModule; - ThrowIfFailed(vk::CreateShaderModule(factory.m_ctx->m_dev, &smCreateInfo, nullptr, &vertModule)); - auto it = factory.m_sharedShaders.emplace(std::make_pair(binHashes[0], std::make_unique(factory, srcHashes[0], binHashes[0], - factory.m_ctx->m_dev, vertModule))).first; + factory.m_ctx->m_dev, *useVertBlob))).first; vertShader = it->second->lock(); } auto fragFind = binHashes[1] ? factory.m_sharedShaders.find(binHashes[1]) : @@ -3286,19 +3316,13 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline binHashes[1] = CompileFrag(fragBlob, fragSource, srcHashes[1], factory); } - smCreateInfo.codeSize = useFragBlob->size() * sizeof(unsigned int); - smCreateInfo.pCode = useFragBlob->data(); - VkShaderModule fragModule; - ThrowIfFailed(vk::CreateShaderModule(factory.m_ctx->m_dev, &smCreateInfo, nullptr, &fragModule)); - auto it = factory.m_sharedShaders.emplace(std::make_pair(binHashes[1], std::make_unique(factory, srcHashes[1], binHashes[1], - factory.m_ctx->m_dev, fragModule))).first; + factory.m_ctx->m_dev, *useFragBlob))).first; fragShader = it->second->lock(); } - VkPipelineCache pipelineCache = VK_NULL_HANDLE; if (pipelineBlob) { @@ -3590,7 +3614,7 @@ void VulkanDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBu VulkanPool* pool = static_cast(p); auto search = pool->m_items.find(static_cast(buf->m_parentData)); if (search != pool->m_items.end()) - (*search)->m_dead = true; + (*search)->m_deadCounter = 3; } GraphicsBufferPoolToken VulkanDataFactoryImpl::newBufferPool() @@ -3666,9 +3690,10 @@ void VulkanCommandQueue::execute() datalk.lock(); for (auto it = gfxF->m_committedData.begin() ; it != gfxF->m_committedData.end() ;) { - if ((*it)->m_dead) + VulkanData* data = *it; + if (data->m_deadCounter && --data->m_deadCounter == 0) { - (*it)->decrement(); + data->decrement(); it = gfxF->m_committedData.erase(it); continue; } @@ -3676,16 +3701,16 @@ void VulkanCommandQueue::execute() } for (auto it = gfxF->m_committedPools.begin() ; it != gfxF->m_committedPools.end() ;) { - if ((*it)->m_dead) + VulkanPool* p = *it; + if (p->m_deadCounter && --p->m_deadCounter == 0) { - VulkanPool* p = *it; it = gfxF->m_committedPools.erase(it); delete p; continue; } else { - (*it)->clearDeadBuffers(); + p->clearDeadBuffers(); } ++it; } diff --git a/lib/x11/WindowXlib.cpp b/lib/x11/WindowXlib.cpp index 60a1646..9f14845 100644 --- a/lib/x11/WindowXlib.cpp +++ b/lib/x11/WindowXlib.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "logvisor/logvisor.hpp" #include "XlibCommon.hpp" @@ -282,6 +283,16 @@ static void genFrameDefault(Screen* screen, int& xOut, int& yOut, int& wOut, int hOut = height; } +static void genFrameDefault(XRRMonitorInfo* screen, int& xOut, int& yOut, int& wOut, int& hOut) +{ + float width = screen->width * 2.0 / 3.0; + float height = screen->height * 2.0 / 3.0; + xOut = (screen->width - width) / 2.0 + screen->x; + yOut = (screen->height - height) / 2.0 + screen->y; + wOut = width; + hOut = height; +} + struct GraphicsContextXlib : IGraphicsContext { EGraphicsAPI m_api; @@ -976,7 +987,13 @@ public: /* Create window */ int x, y, w, h; - genFrameDefault(screen, x, y, w, h); + int nmonitors = 0; + XRRMonitorInfo* mInfo = XRRGetMonitors(m_xDisp, screen->root, true, &nmonitors); + if (nmonitors) + genFrameDefault(mInfo, x, y, w, h); + else + genFrameDefault(screen, x, y, w, h); + XRRFreeMonitors(mInfo); XSetWindowAttributes swa; swa.colormap = m_colormapId; swa.border_pixmap = 0; @@ -1042,6 +1059,7 @@ public: XMapWindow(m_xDisp, m_windowId); setStyle(EWindowStyle::Default); setCursor(EMouseCursor::Pointer); + setWindowFrameDefault(); XFlush(m_xDisp); if (!m_gfxCtx->initializeContext(vulkanHandle)) @@ -1150,9 +1168,14 @@ public: void setWindowFrameDefault() { - int x, y, w, h; + int x, y, w, h, nmonitors; Screen* screen = DefaultScreenOfDisplay(m_xDisp); - genFrameDefault(screen, x, y, w, h); + XRRMonitorInfo* mInfo = XRRGetMonitors(m_xDisp, screen->root, true, &nmonitors); + if (nmonitors) + genFrameDefault(mInfo, x, y, w, h); + else + genFrameDefault(screen, x, y, w, h); + XRRFreeMonitors(mInfo); XWindowChanges values = {(int)x, (int)y, (int)w, (int)h}; XLockDisplay(m_xDisp); XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values); diff --git a/logvisor b/logvisor index f8ab0e0..bfe0c1c 160000 --- a/logvisor +++ b/logvisor @@ -1 +1 @@ -Subproject commit f8ab0e03bae0cad2541f551350dcafb91477b007 +Subproject commit bfe0c1ccad9ee545a6ab9c0b295258c47b55da3c