diff --git a/common/gl_obj.cc b/common/gl_obj.cc index f58e56f..f51c2e9 100644 --- a/common/gl_obj.cc +++ b/common/gl_obj.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "common/aggregate_promise.hh" @@ -278,8 +279,7 @@ try { LockedAttachmentsFuture::Promise pro {ctx}; // lock array buffers - std::vector attrs_fu; - attrs_fu.reserve(attrs.size()); + std::unordered_map attrs_fu_map; for (size_t i = 0; i < attrs.size(); ++i) { const auto& attr = attrs[i]; @@ -292,8 +292,20 @@ try { static_cast(attr.stride) * (vhint.instances-1) + attr.offset: size_t {0}; - attrs_fu.push_back(Lock(attr.buffer, gl::BufferTarget::Array, required)); - apro.Add(attrs_fu.back()); + if (attrs_fu_map.end() == attrs_fu_map.find(attr.buffer)) { + auto [itr, add] = attrs_fu_map.emplace( + attr.buffer, Lock(attr.buffer, gl::BufferTarget::Array, required)); + (void) add; + apro.Add(itr->second); + } + } + + // serialize attrs_fu_map + std::vector attrs_fu; + for (const auto& attr : attrs) { + auto itr = attrs_fu_map.find(attr.buffer); + assert(itr != attrs_fu_map.end()); + attrs_fu.push_back(itr->second); } // lock index buffers (it must be the last element in `fus`) @@ -367,6 +379,20 @@ Obj_FramebufferMeta::LockedAttachmentsFuture Obj_FramebufferMeta::LockAttachment try { auto ret = std::make_shared(); + // file duplication check for preventing deadlock by double lock + std::unordered_set locked; + for (const auto& col : colors) { + if (col->tex && !locked.insert(col->tex).second) { + throw nf7::Exception {"attached color texture is duplicated"}; + } + } + if (depth && !locked.insert(depth->tex).second) { + throw nf7::Exception {"attached depth texture is duplicated"}; + } + if (stencil && !locked.insert(stencil->tex).second) { + throw nf7::Exception {"attached stencil texture is duplicated"}; + } + nf7::AggregatePromise apro {ctx}; LockedAttachmentsFuture::Promise pro {ctx};