Addresses some resource lifetime issues in OpenGL and Vulkan

This commit is contained in:
Jack Andersen 2017-11-01 23:24:50 -10:00
parent 10364557b9
commit 0f96af94f6
6 changed files with 369 additions and 255 deletions

View File

@ -192,7 +192,7 @@ else(NOT GEKKO)
endif() endif()
include_directories(${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) 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") if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
message(STATUS "Enabling Vulkan support") message(STATUS "Enabling Vulkan support")

View File

@ -95,6 +95,7 @@ public:
{ m_parent = other.m_parent; other.m_parent = nullptr; return *this; } { m_parent = other.m_parent; other.m_parent = nullptr; return *this; }
Token(Token&& other) Token(Token&& other)
{ m_parent = other.m_parent; other.m_parent = nullptr; } { 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(); } ~Token() { if (m_parent) m_parent->decrement(); }
operator bool() const { return m_parent != nullptr; } operator bool() const { return m_parent != nullptr; }
ShaderImpl& get() const { return static_cast<ShaderImpl&>(*m_parent); } ShaderImpl& get() const { return static_cast<ShaderImpl&>(*m_parent); }

View File

@ -67,6 +67,7 @@ public:
ThreadLocalPtr<struct GLData> GLDataFactoryImpl::m_deferredData; ThreadLocalPtr<struct GLData> GLDataFactoryImpl::m_deferredData;
struct GLData : IGraphicsDataPriv struct GLData : IGraphicsDataPriv
{ {
int m_deadCounter = 0;
std::vector<std::unique_ptr<class GLShaderPipeline>> m_SPs; std::vector<std::unique_ptr<class GLShaderPipeline>> m_SPs;
std::vector<std::unique_ptr<struct GLShaderDataBinding>> m_SBinds; std::vector<std::unique_ptr<struct GLShaderDataBinding>> m_SBinds;
std::vector<std::unique_ptr<class GLGraphicsBufferS>> m_SBufs; std::vector<std::unique_ptr<class GLGraphicsBufferS>> m_SBufs;
@ -85,6 +86,7 @@ struct GLPoolItem : IGraphicsDataPriv
struct GLPool : IGraphicsBufferPool struct GLPool : IGraphicsBufferPool
{ {
int m_deadCounter = 0;
std::unordered_set<GLPoolItem*> m_items; std::unordered_set<GLPoolItem*> m_items;
~GLPool() ~GLPool()
{ {
@ -450,9 +452,9 @@ class GLShaderPipeline : public IShaderPipeline
friend class GLDataFactory; friend class GLDataFactory;
friend struct GLCommandQueue; friend struct GLCommandQueue;
friend struct GLShaderDataBinding; friend struct GLShaderDataBinding;
GLShareableShader::Token m_vert; mutable GLShareableShader::Token m_vert;
GLShareableShader::Token m_frag; mutable GLShareableShader::Token m_frag;
GLuint m_prog = 0; mutable GLuint m_prog = 0;
GLenum m_sfactor = GL_ONE; GLenum m_sfactor = GL_ONE;
GLenum m_dfactor = GL_ZERO; GLenum m_dfactor = GL_ZERO;
GLenum m_drawPrim = GL_TRIANGLES; GLenum m_drawPrim = GL_TRIANGLES;
@ -462,10 +464,11 @@ class GLShaderPipeline : public IShaderPipeline
bool m_alphaWrite = true; bool m_alphaWrite = true;
bool m_subtractBlend = false; bool m_subtractBlend = false;
CullMode m_culling; CullMode m_culling;
std::vector<GLint> m_uniLocs; mutable std::vector<GLint> m_uniLocs;
mutable std::vector<std::string> m_texNames;
mutable std::vector<std::string> m_blockNames;
GLShaderPipeline(GLData* parent) : IShaderPipeline(parent) {} GLShaderPipeline(GLData* parent) : IShaderPipeline(parent) {}
public: public:
operator bool() const {return m_prog != 0;}
~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); } ~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); }
GLShaderPipeline& operator=(const GLShaderPipeline&) = delete; GLShaderPipeline& operator=(const GLShaderPipeline&) = delete;
GLShaderPipeline(const GLShaderPipeline&) = delete; GLShaderPipeline(const GLShaderPipeline&) = delete;
@ -485,6 +488,8 @@ public:
m_subtractBlend = other.m_subtractBlend; m_subtractBlend = other.m_subtractBlend;
m_culling = other.m_culling; m_culling = other.m_culling;
m_uniLocs = std::move(other.m_uniLocs); m_uniLocs = std::move(other.m_uniLocs);
m_texNames = std::move(other.m_texNames);
m_blockNames = std::move(other.m_blockNames);
return *this; return *this;
} }
GLShaderPipeline(GLShaderPipeline&& other) GLShaderPipeline(GLShaderPipeline&& other)
@ -492,8 +497,72 @@ public:
GLuint bind() const GLuint bind() const
{ {
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); glUseProgram(m_prog);
if (m_blockNames.size())
{
m_uniLocs.reserve(m_blockNames.size());
for (size_t i=0 ; i<m_blockNames.size() ; ++i)
{
GLint uniLoc = glGetUniformBlockIndex(m_prog, m_blockNames[i].c_str());
//if (uniLoc < 0)
// Log.report(logvisor::Warning, "unable to find uniform block '%s'", uniformBlockNames[i]);
m_uniLocs.push_back(uniLoc);
}
m_blockNames = std::vector<std::string>();
}
if (m_texNames.size())
{
for (int i=0 ; i<m_texNames.size() ; ++i)
{
GLint texLoc = glGetUniformLocation(m_prog, m_texNames[i].c_str());
if (texLoc < 0)
{ /* Log.report(logvisor::Warning, "unable to find sampler variable '%s'", texNames[i]); */ }
else
glUniform1i(texLoc, i);
}
m_texNames = std::vector<std::string>();
}
}
else
{
glUseProgram(m_prog);
}
if (m_dfactor != GL_ZERO) if (m_dfactor != GL_ZERO)
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
@ -654,54 +723,13 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline
shader.m_frag = it->second->lock(); shader.m_frag = it->second->lock();
} }
shader.m_prog = glCreateProgram(); shader.m_texNames.reserve(texCount);
if (!shader.m_prog)
{
Log.report(logvisor::Error, "unable to create shader program");
return nullptr;
}
glAttachShader(shader.m_prog, shader.m_vert.get().m_shader);
glAttachShader(shader.m_prog, shader.m_frag.get().m_shader);
glLinkProgram(shader.m_prog);
glGetProgramiv(shader.m_prog, GL_LINK_STATUS, &status);
if (status != GL_TRUE)
{
GLint logLen;
glGetProgramiv(shader.m_prog, GL_INFO_LOG_LENGTH, &logLen);
char* log = (char*)malloc(logLen);
glGetProgramInfoLog(shader.m_prog, logLen, nullptr, log);
Log.report(logvisor::Error, "unable to link shader program\n%s\n", log);
free(log);
return nullptr;
}
glUseProgram(shader.m_prog);
if (uniformBlockCount)
{
shader.m_uniLocs.reserve(uniformBlockCount);
for (size_t i=0 ; i<uniformBlockCount ; ++i)
{
GLint uniLoc = glGetUniformBlockIndex(shader.m_prog, uniformBlockNames[i]);
//if (uniLoc < 0)
// Log.report(logvisor::Warning, "unable to find uniform block '%s'", uniformBlockNames[i]);
shader.m_uniLocs.push_back(uniLoc);
}
}
if (texCount && texNames)
{
for (int i=0 ; i<texCount ; ++i) for (int i=0 ; i<texCount ; ++i)
{ shader.m_texNames.emplace_back(texNames[i]);
GLint texLoc = glGetUniformLocation(shader.m_prog, texNames[i]);
if (texLoc < 0) shader.m_blockNames.reserve(uniformBlockCount);
{ /* Log.report(logvisor::Warning, "unable to find sampler variable '%s'", texNames[i]); */ } for (int i=0 ; i<uniformBlockCount ; ++i)
else shader.m_blockNames.emplace_back(uniformBlockNames[i]);
glUniform1i(texLoc, i);
}
}
if (srcFac == BlendFactor::Subtract || dstFac == BlendFactor::Subtract) if (srcFac == BlendFactor::Subtract || dstFac == BlendFactor::Subtract)
{ {
@ -926,8 +954,9 @@ void GLDataFactoryImpl::destroyData(IGraphicsData* d)
{ {
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
GLData* data = static_cast<GLData*>(d); GLData* data = static_cast<GLData*>(d);
m_committedData.erase(data); data->m_deadCounter = 3;
data->decrement(); //m_committedData.erase(data);
//data->decrement();
} }
void GLDataFactoryImpl::destroyAllData() void GLDataFactoryImpl::destroyAllData()
@ -945,8 +974,9 @@ void GLDataFactoryImpl::destroyPool(IGraphicsBufferPool* p)
{ {
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
GLPool* pool = static_cast<GLPool*>(p); GLPool* pool = static_cast<GLPool*>(p);
m_committedPools.erase(pool); pool->m_deadCounter = 3;
delete pool; //m_committedPools.erase(pool);
//delete pool;
} }
IGraphicsBufferD* GLDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, IGraphicsBufferD* GLDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
@ -1094,9 +1124,9 @@ struct GLCommandQueue : IGraphicsCommandQueue
std::vector<std::function<void(void)>> m_pendingPosts1; std::vector<std::function<void(void)>> m_pendingPosts1;
std::vector<std::function<void(void)>> m_pendingPosts2; std::vector<std::function<void(void)>> m_pendingPosts2;
std::vector<GLVertexFormat*> m_pendingFmtAdds; std::vector<GLVertexFormat*> m_pendingFmtAdds;
std::vector<std::array<GLuint, 3>> m_pendingFmtDels; //std::vector<std::array<GLuint, 3>> m_pendingFmtDels;
std::vector<GLTextureR*> m_pendingFboAdds; std::vector<GLTextureR*> m_pendingFboAdds;
std::vector<GLuint> m_pendingFboDels; //std::vector<GLuint> m_pendingFboDels;
static void ConfigureVertexFormat(GLVertexFormat* fmt) static void ConfigureVertexFormat(GLVertexFormat* fmt)
{ {
@ -1213,6 +1243,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
self->m_pendingFmtAdds.clear(); self->m_pendingFmtAdds.clear();
} }
#if 0
if (self->m_pendingFmtDels.size()) if (self->m_pendingFmtDels.size())
{ {
for (const auto& fmt : self->m_pendingFmtDels) for (const auto& fmt : self->m_pendingFmtDels)
@ -1226,12 +1257,14 @@ struct GLCommandQueue : IGraphicsCommandQueue
glDeleteFramebuffers(1, &fbo); glDeleteFramebuffers(1, &fbo);
self->m_pendingFboDels.clear(); self->m_pendingFboDels.clear();
} }
#endif
if (self->m_pendingPosts2.size()) if (self->m_pendingPosts2.size())
posts.swap(self->m_pendingPosts2); posts.swap(self->m_pendingPosts2);
} }
std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf]; std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf];
GLenum currentPrim = GL_TRIANGLES; GLenum currentPrim = GL_TRIANGLES;
const GLShaderDataBinding* curBinding = nullptr;
for (const Command& cmd : cmds) for (const Command& cmd : cmds)
{ {
switch (cmd.m_op) switch (cmd.m_op)
@ -1240,6 +1273,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
{ {
const GLShaderDataBinding* binding = static_cast<const GLShaderDataBinding*>(cmd.binding); const GLShaderDataBinding* binding = static_cast<const GLShaderDataBinding*>(cmd.binding);
binding->bind(self->m_drawBuf); binding->bind(self->m_drawBuf);
curBinding = binding;
currentPrim = binding->m_pipeline->m_drawPrim; currentPrim = binding->m_pipeline->m_drawPrim;
break; break;
} }
@ -1332,6 +1366,31 @@ struct GLCommandQueue : IGraphicsCommandQueue
cmds.clear(); cmds.clear();
for (auto& p : posts) for (auto& p : posts)
p(); p();
GLDataFactoryImpl* gfxF = static_cast<GLDataFactoryImpl*>(self->m_parent->getDataFactory());
std::unique_lock<std::mutex> 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) void delVertexFormat(GLVertexFormat* fmt)
{ {
#if 0
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
bool foundAdd = false; bool foundAdd = false;
for (GLVertexFormat*& afmt : m_pendingFmtAdds) for (GLVertexFormat*& afmt : m_pendingFmtAdds)
@ -1507,6 +1567,8 @@ struct GLCommandQueue : IGraphicsCommandQueue
} }
if (!foundAdd) if (!foundAdd)
m_pendingFmtDels.push_back({fmt->m_vao[0], fmt->m_vao[1], fmt->m_vao[2]}); 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) void addFBO(GLTextureR* tex)
@ -1517,8 +1579,11 @@ struct GLCommandQueue : IGraphicsCommandQueue
void delFBO(GLTextureR* tex) void delFBO(GLTextureR* tex)
{ {
#if 0
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_pendingFboDels.push_back(tex->m_fbo); m_pendingFboDels.push_back(tex->m_fbo);
#endif
glDeleteFramebuffers(1, &tex->m_fbo);
} }
void execute() void execute()

View File

@ -26,11 +26,10 @@ class VulkanDataFactoryImpl;
struct VulkanShareableShader : IShareableShader<VulkanDataFactoryImpl, VulkanShareableShader> struct VulkanShareableShader : IShareableShader<VulkanDataFactoryImpl, VulkanShareableShader>
{ {
VkDevice m_dev; VkDevice m_dev;
VkShaderModule m_shader; std::vector<unsigned int> m_shader;
VulkanShareableShader(VulkanDataFactoryImpl& fac, uint64_t srcKey, uint64_t binKey, VulkanShareableShader(VulkanDataFactoryImpl& fac, uint64_t srcKey, uint64_t binKey,
VkDevice dev, VkShaderModule s) VkDevice dev, const std::vector<unsigned int>& s)
: IShareableShader(fac, srcKey, binKey), m_dev(dev), m_shader(s) {} : IShareableShader(fac, srcKey, binKey), m_dev(dev), m_shader(s) {}
~VulkanShareableShader() { vk::DestroyShaderModule(m_dev, m_shader, nullptr); }
}; };
class VulkanDataFactoryImpl : public VulkanDataFactory class VulkanDataFactoryImpl : public VulkanDataFactory
@ -338,8 +337,8 @@ void VulkanContext::initVulkan(const char* appName)
#ifndef NDEBUG #ifndef NDEBUG
m_layerNames.push_back("VK_LAYER_LUNARG_core_validation"); 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_object_tracker");
m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation"); //m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation");
m_layerNames.push_back("VK_LAYER_GOOGLE_threading"); //m_layerNames.push_back("VK_LAYER_GOOGLE_threading");
#endif #endif
demo_check_layers(m_instanceLayerProperties, m_layerNames); demo_check_layers(m_instanceLayerProperties, m_layerNames);
@ -753,7 +752,7 @@ struct VulkanData : IGraphicsDataPriv
std::vector<std::unique_ptr<class VulkanTextureD>> m_DTexs; std::vector<std::unique_ptr<class VulkanTextureD>> m_DTexs;
std::vector<std::unique_ptr<class VulkanTextureR>> m_RTexs; std::vector<std::unique_ptr<class VulkanTextureR>> m_RTexs;
std::vector<std::unique_ptr<struct VulkanVertexFormat>> m_VFmts; std::vector<std::unique_ptr<struct VulkanVertexFormat>> m_VFmts;
bool m_dead = false; int m_deadCounter = 0;
VulkanData(VulkanContext* ctx) : m_ctx(ctx) {} VulkanData(VulkanContext* ctx) : m_ctx(ctx) {}
~VulkanData() ~VulkanData()
{ {
@ -769,7 +768,7 @@ struct VulkanPoolItem : IGraphicsDataPriv
VulkanContext* m_ctx; VulkanContext* m_ctx;
VkDeviceMemory m_bufMem = VK_NULL_HANDLE; VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
std::unique_ptr<class VulkanGraphicsBufferD> m_buf; std::unique_ptr<class VulkanGraphicsBufferD> m_buf;
bool m_dead = false; int m_deadCounter = 0;
VulkanPoolItem(VulkanContext* ctx) : m_ctx(ctx) {} VulkanPoolItem(VulkanContext* ctx) : m_ctx(ctx) {}
~VulkanPoolItem() ~VulkanPoolItem()
{ {
@ -781,7 +780,7 @@ struct VulkanPoolItem : IGraphicsDataPriv
struct VulkanPool : IGraphicsBufferPool struct VulkanPool : IGraphicsBufferPool
{ {
std::unordered_set<VulkanPoolItem*> m_items; std::unordered_set<VulkanPoolItem*> m_items;
bool m_dead = false; int m_deadCounter = 0;
~VulkanPool() ~VulkanPool()
{ {
for (auto& item : m_items) for (auto& item : m_items)
@ -792,7 +791,7 @@ struct VulkanPool : IGraphicsBufferPool
{ {
for (auto it = m_items.begin() ; it != m_items.end() ;) 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)->decrement();
it = m_items.erase(it); it = m_items.erase(it);
@ -1881,8 +1880,18 @@ class VulkanShaderPipeline : public IShaderPipeline
VulkanContext* m_ctx; VulkanContext* m_ctx;
VkPipelineCache m_pipelineCache; VkPipelineCache m_pipelineCache;
const VulkanVertexFormat* m_vtxFmt; const VulkanVertexFormat* m_vtxFmt;
VulkanShareableShader::Token m_vert; mutable VulkanShareableShader::Token m_vert;
VulkanShareableShader::Token m_frag; 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, VulkanShaderPipeline(IGraphicsData* parent,
VulkanContext* ctx, VulkanContext* ctx,
VulkanShareableShader::Token&& vert, VulkanShareableShader::Token&& vert,
@ -1893,10 +1902,26 @@ class VulkanShaderPipeline : public IShaderPipeline
ZTest depthTest, bool depthWrite, bool colorWrite, ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling) bool alphaWrite, CullMode culling)
: IShaderPipeline(parent), m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), : IShaderPipeline(parent), m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt),
m_vert(std::move(vert)), m_frag(std::move(frag)) 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:
~VulkanShaderPipeline()
{
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; VkCullModeFlagBits cullMode;
switch (culling) switch (m_culling)
{ {
case CullMode::None: case CullMode::None:
default: default:
@ -1919,11 +1944,23 @@ class VulkanShaderPipeline : public IShaderPipeline
VkPipelineShaderStageCreateInfo stages[2] = {}; 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].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stages[0].pNext = nullptr; stages[0].pNext = nullptr;
stages[0].flags = 0; stages[0].flags = 0;
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
stages[0].module = m_vert.get().m_shader; stages[0].module = vertModule;
stages[0].pName = "main"; stages[0].pName = "main";
stages[0].pSpecializationInfo = nullptr; stages[0].pSpecializationInfo = nullptr;
@ -1931,7 +1968,7 @@ class VulkanShaderPipeline : public IShaderPipeline
stages[1].pNext = nullptr; stages[1].pNext = nullptr;
stages[1].flags = 0; stages[1].flags = 0;
stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
stages[1].module = m_frag.get().m_shader; stages[1].module = fragModule;
stages[1].pName = "main"; stages[1].pName = "main";
stages[1].pSpecializationInfo = nullptr; stages[1].pSpecializationInfo = nullptr;
@ -1939,7 +1976,7 @@ class VulkanShaderPipeline : public IShaderPipeline
assemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; assemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
assemblyInfo.pNext = nullptr; assemblyInfo.pNext = nullptr;
assemblyInfo.flags = 0; assemblyInfo.flags = 0;
assemblyInfo.topology = PRIMITIVE_TABLE[int(prim)]; assemblyInfo.topology = PRIMITIVE_TABLE[int(m_prim)];
assemblyInfo.primitiveRestartEnable = VK_FALSE; assemblyInfo.primitiveRestartEnable = VK_FALSE;
VkPipelineViewportStateCreateInfo viewportInfo = {}; VkPipelineViewportStateCreateInfo viewportInfo = {};
@ -1975,12 +2012,12 @@ class VulkanShaderPipeline : public IShaderPipeline
depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencilInfo.pNext = nullptr; depthStencilInfo.pNext = nullptr;
depthStencilInfo.flags = 0; depthStencilInfo.flags = 0;
depthStencilInfo.depthTestEnable = depthTest != ZTest::None; depthStencilInfo.depthTestEnable = m_depthTest != ZTest::None;
depthStencilInfo.depthWriteEnable = depthWrite; depthStencilInfo.depthWriteEnable = m_depthWrite;
depthStencilInfo.front.compareOp = VK_COMPARE_OP_ALWAYS; depthStencilInfo.front.compareOp = VK_COMPARE_OP_ALWAYS;
depthStencilInfo.back.compareOp = VK_COMPARE_OP_ALWAYS; depthStencilInfo.back.compareOp = VK_COMPARE_OP_ALWAYS;
switch (depthTest) switch (m_depthTest)
{ {
case ZTest::None: case ZTest::None:
default: default:
@ -1998,8 +2035,8 @@ class VulkanShaderPipeline : public IShaderPipeline
} }
VkPipelineColorBlendAttachmentState colorAttachment = {}; VkPipelineColorBlendAttachmentState colorAttachment = {};
colorAttachment.blendEnable = dstFac != BlendFactor::Zero; colorAttachment.blendEnable = m_dstFac != BlendFactor::Zero;
if (srcFac == BlendFactor::Subtract || dstFac == BlendFactor::Subtract) if (m_srcFac == BlendFactor::Subtract || m_dstFac == BlendFactor::Subtract)
{ {
colorAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR; colorAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR;
colorAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; colorAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR;
@ -2007,18 +2044,18 @@ class VulkanShaderPipeline : public IShaderPipeline
} }
else else
{ {
colorAttachment.srcColorBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; colorAttachment.srcColorBlendFactor = BLEND_FACTOR_TABLE[int(m_srcFac)];
colorAttachment.dstColorBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)]; colorAttachment.dstColorBlendFactor = BLEND_FACTOR_TABLE[int(m_dstFac)];
colorAttachment.colorBlendOp = VK_BLEND_OP_ADD; colorAttachment.colorBlendOp = VK_BLEND_OP_ADD;
} }
colorAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; colorAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; colorAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorAttachment.alphaBlendOp = VK_BLEND_OP_ADD; colorAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
colorAttachment.colorWriteMask = colorAttachment.colorWriteMask =
(colorWrite ? (VK_COLOR_COMPONENT_R_BIT | (m_colorWrite ? (VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT) : 0) | VK_COLOR_COMPONENT_B_BIT) : 0) |
(alphaWrite ? VK_COLOR_COMPONENT_A_BIT : 0); (m_alphaWrite ? VK_COLOR_COMPONENT_A_BIT : 0);
VkPipelineColorBlendStateCreateInfo colorBlendInfo = {}; VkPipelineColorBlendStateCreateInfo colorBlendInfo = {};
colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
@ -2034,7 +2071,7 @@ class VulkanShaderPipeline : public IShaderPipeline
pipelineCreateInfo.flags = 0; pipelineCreateInfo.flags = 0;
pipelineCreateInfo.stageCount = 2; pipelineCreateInfo.stageCount = 2;
pipelineCreateInfo.pStages = stages; pipelineCreateInfo.pStages = stages;
pipelineCreateInfo.pVertexInputState = &vtxFmt->m_info; pipelineCreateInfo.pVertexInputState = &m_vtxFmt->m_info;
pipelineCreateInfo.pInputAssemblyState = &assemblyInfo; pipelineCreateInfo.pInputAssemblyState = &assemblyInfo;
pipelineCreateInfo.pViewportState = &viewportInfo; pipelineCreateInfo.pViewportState = &viewportInfo;
pipelineCreateInfo.pRasterizationState = &rasterizationInfo; pipelineCreateInfo.pRasterizationState = &rasterizationInfo;
@ -2042,22 +2079,20 @@ class VulkanShaderPipeline : public IShaderPipeline
pipelineCreateInfo.pDepthStencilState = &depthStencilInfo; pipelineCreateInfo.pDepthStencilState = &depthStencilInfo;
pipelineCreateInfo.pColorBlendState = &colorBlendInfo; pipelineCreateInfo.pColorBlendState = &colorBlendInfo;
pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.pDynamicState = &dynamicState;
pipelineCreateInfo.layout = ctx->m_pipelinelayout; pipelineCreateInfo.layout = m_ctx->m_pipelinelayout;
pipelineCreateInfo.renderPass = ctx->m_pass; pipelineCreateInfo.renderPass = m_ctx->m_pass;
ThrowIfFailed(vk::CreateGraphicsPipelines(ctx->m_dev, pipelineCache, 1, &pipelineCreateInfo, ThrowIfFailed(vk::CreateGraphicsPipelines(m_ctx->m_dev, m_pipelineCache, 1, &pipelineCreateInfo,
nullptr, &m_pipeline)); 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();
} }
public: return m_pipeline;
VkPipeline m_pipeline;
~VulkanShaderPipeline()
{
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;
}; };
static VkDeviceSize SizeBufferForGPU(IGraphicsBuffer* buf, VulkanContext* ctx, static VkDeviceSize SizeBufferForGPU(IGraphicsBuffer* buf, VulkanContext* ctx,
@ -2156,7 +2191,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv
std::unique_ptr<IGraphicsBuffer*[]> m_ubufs; std::unique_ptr<IGraphicsBuffer*[]> m_ubufs;
std::vector<std::array<VkDescriptorBufferInfo, 2>> m_ubufOffs; std::vector<std::array<VkDescriptorBufferInfo, 2>> m_ubufOffs;
size_t m_texCount; size_t m_texCount;
VkImageView m_knownViewHandles[2][8] = {}; VkImageView m_knownViewHandles[2][BOO_GLSL_MAX_TEXTURE_COUNT] = {};
struct BindTex struct BindTex
{ {
ITexture* tex; ITexture* tex;
@ -2402,7 +2437,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv
if (totalWrites) if (totalWrites)
vk::UpdateDescriptorSets(m_ctx->m_dev, totalWrites, writes, 0, nullptr); 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]) if (m_descSets[b])
vk::CmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_ctx->m_pipelinelayout, vk::CmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_ctx->m_pipelinelayout,
0, 1, &m_descSets[b], 0, nullptr); 0, 1, &m_descSets[b], 0, nullptr);
@ -3023,13 +3058,13 @@ void VulkanTextureD::unmap()
void VulkanDataFactoryImpl::destroyData(IGraphicsData* d) void VulkanDataFactoryImpl::destroyData(IGraphicsData* d)
{ {
VulkanData* data = static_cast<VulkanData*>(d); VulkanData* data = static_cast<VulkanData*>(d);
data->m_dead = true; data->m_deadCounter = 3;
} }
void VulkanDataFactoryImpl::destroyPool(IGraphicsBufferPool* p) void VulkanDataFactoryImpl::destroyPool(IGraphicsBufferPool* p)
{ {
VulkanPool* pool = static_cast<VulkanPool*>(p); VulkanPool* pool = static_cast<VulkanPool*>(p);
pool->m_dead = true; pool->m_deadCounter = 3;
} }
void VulkanDataFactoryImpl::destroyAllData() void VulkanDataFactoryImpl::destroyAllData()
@ -3255,15 +3290,10 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
binHashes[0] = CompileVert(vertBlob, vertSource, srcHashes[0], factory); 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 = auto it =
factory.m_sharedShaders.emplace(std::make_pair(binHashes[0], factory.m_sharedShaders.emplace(std::make_pair(binHashes[0],
std::make_unique<VulkanShareableShader>(factory, srcHashes[0], binHashes[0], std::make_unique<VulkanShareableShader>(factory, srcHashes[0], binHashes[0],
factory.m_ctx->m_dev, vertModule))).first; factory.m_ctx->m_dev, *useVertBlob))).first;
vertShader = it->second->lock(); vertShader = it->second->lock();
} }
auto fragFind = binHashes[1] ? factory.m_sharedShaders.find(binHashes[1]) : 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); 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 = auto it =
factory.m_sharedShaders.emplace(std::make_pair(binHashes[1], factory.m_sharedShaders.emplace(std::make_pair(binHashes[1],
std::make_unique<VulkanShareableShader>(factory, srcHashes[1], binHashes[1], std::make_unique<VulkanShareableShader>(factory, srcHashes[1], binHashes[1],
factory.m_ctx->m_dev, fragModule))).first; factory.m_ctx->m_dev, *useFragBlob))).first;
fragShader = it->second->lock(); fragShader = it->second->lock();
} }
VkPipelineCache pipelineCache = VK_NULL_HANDLE; VkPipelineCache pipelineCache = VK_NULL_HANDLE;
if (pipelineBlob) if (pipelineBlob)
{ {
@ -3590,7 +3614,7 @@ void VulkanDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBu
VulkanPool* pool = static_cast<VulkanPool*>(p); VulkanPool* pool = static_cast<VulkanPool*>(p);
auto search = pool->m_items.find(static_cast<VulkanPoolItem*>(buf->m_parentData)); auto search = pool->m_items.find(static_cast<VulkanPoolItem*>(buf->m_parentData));
if (search != pool->m_items.end()) if (search != pool->m_items.end())
(*search)->m_dead = true; (*search)->m_deadCounter = 3;
} }
GraphicsBufferPoolToken VulkanDataFactoryImpl::newBufferPool() GraphicsBufferPoolToken VulkanDataFactoryImpl::newBufferPool()
@ -3666,26 +3690,27 @@ void VulkanCommandQueue::execute()
datalk.lock(); datalk.lock();
for (auto it = gfxF->m_committedData.begin() ; it != gfxF->m_committedData.end() ;) 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); it = gfxF->m_committedData.erase(it);
continue; continue;
} }
++it; ++it;
} }
for (auto it = gfxF->m_committedPools.begin() ; it != gfxF->m_committedPools.end() ;) for (auto it = gfxF->m_committedPools.begin() ; it != gfxF->m_committedPools.end() ;)
{
if ((*it)->m_dead)
{ {
VulkanPool* p = *it; VulkanPool* p = *it;
if (p->m_deadCounter && --p->m_deadCounter == 0)
{
it = gfxF->m_committedPools.erase(it); it = gfxF->m_committedPools.erase(it);
delete p; delete p;
continue; continue;
} }
else else
{ {
(*it)->clearDeadBuffers(); p->clearDeadBuffers();
} }
++it; ++it;
} }

View File

@ -28,6 +28,7 @@
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#include "logvisor/logvisor.hpp" #include "logvisor/logvisor.hpp"
#include "XlibCommon.hpp" #include "XlibCommon.hpp"
@ -282,6 +283,16 @@ static void genFrameDefault(Screen* screen, int& xOut, int& yOut, int& wOut, int
hOut = height; 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 struct GraphicsContextXlib : IGraphicsContext
{ {
EGraphicsAPI m_api; EGraphicsAPI m_api;
@ -976,7 +987,13 @@ public:
/* Create window */ /* Create window */
int x, y, w, h; int 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); genFrameDefault(screen, x, y, w, h);
XRRFreeMonitors(mInfo);
XSetWindowAttributes swa; XSetWindowAttributes swa;
swa.colormap = m_colormapId; swa.colormap = m_colormapId;
swa.border_pixmap = 0; swa.border_pixmap = 0;
@ -1042,6 +1059,7 @@ public:
XMapWindow(m_xDisp, m_windowId); XMapWindow(m_xDisp, m_windowId);
setStyle(EWindowStyle::Default); setStyle(EWindowStyle::Default);
setCursor(EMouseCursor::Pointer); setCursor(EMouseCursor::Pointer);
setWindowFrameDefault();
XFlush(m_xDisp); XFlush(m_xDisp);
if (!m_gfxCtx->initializeContext(vulkanHandle)) if (!m_gfxCtx->initializeContext(vulkanHandle))
@ -1150,9 +1168,14 @@ public:
void setWindowFrameDefault() void setWindowFrameDefault()
{ {
int x, y, w, h; int x, y, w, h, nmonitors;
Screen* screen = DefaultScreenOfDisplay(m_xDisp); Screen* screen = DefaultScreenOfDisplay(m_xDisp);
XRRMonitorInfo* mInfo = XRRGetMonitors(m_xDisp, screen->root, true, &nmonitors);
if (nmonitors)
genFrameDefault(mInfo, x, y, w, h);
else
genFrameDefault(screen, x, y, w, h); genFrameDefault(screen, x, y, w, h);
XRRFreeMonitors(mInfo);
XWindowChanges values = {(int)x, (int)y, (int)w, (int)h}; XWindowChanges values = {(int)x, (int)y, (int)w, (int)h};
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values); XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values);

@ -1 +1 @@
Subproject commit f8ab0e03bae0cad2541f551350dcafb91477b007 Subproject commit bfe0c1ccad9ee545a6ab9c0b295258c47b55da3c