program build should failed if there is created kernel attached to program

piglit error:
"Trigger CL_INVALID_OPERATION if there are kernel objects attached to program"
---
 src/gallium/state_trackers/clover/api/kernel.cpp   | 10 ++++++++--
 src/gallium/state_trackers/clover/core/kernel.cpp  |  1 +
 src/gallium/state_trackers/clover/core/program.cpp | 14 ++++++++++++++
 src/gallium/state_trackers/clover/core/program.hpp |  4 ++++
 4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/gallium/state_trackers/clover/api/kernel.cpp 
b/src/gallium/state_trackers/clover/api/kernel.cpp
index 05cc392..69f7d6c 100644
--- a/src/gallium/state_trackers/clover/api/kernel.cpp
+++ b/src/gallium/state_trackers/clover/api/kernel.cpp
@@ -76,7 +76,10 @@ clCreateKernelsInProgram(cl_program d_prog, cl_uint count,
 
 CLOVER_API cl_int
 clRetainKernel(cl_kernel d_kern) try {
-   obj(d_kern).retain();
+   auto &kern = obj(d_kern);
+   kern.retain();
+   program &prog = kern.program;
+   prog.ref_kernel(kern.name());
    return CL_SUCCESS;
 
 } catch (error &e) {
@@ -85,7 +88,10 @@ clRetainKernel(cl_kernel d_kern) try {
 
 CLOVER_API cl_int
 clReleaseKernel(cl_kernel d_kern) try {
-   if (obj(d_kern).release())
+   auto &kern = obj(d_kern);
+   program &prog = kern.program;
+   prog.unref_kernel(kern.name());
+   if (kern.release())
       delete pobj(d_kern);
 
    return CL_SUCCESS;
diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp 
b/src/gallium/state_trackers/clover/core/kernel.cpp
index 5e5fe51..c670253 100644
--- a/src/gallium/state_trackers/clover/core/kernel.cpp
+++ b/src/gallium/state_trackers/clover/core/kernel.cpp
@@ -51,6 +51,7 @@ kernel::kernel(clover::program &prog, const std::string &name,
       else
          throw error(CL_INVALID_KERNEL_DEFINITION);
    }
+   prog.ref_kernel(name);
 }
 
 template<typename V>
diff --git a/src/gallium/state_trackers/clover/core/program.cpp 
b/src/gallium/state_trackers/clover/core/program.cpp
index e09c3aa..dbfa284 100644
--- a/src/gallium/state_trackers/clover/core/program.cpp
+++ b/src/gallium/state_trackers/clover/core/program.cpp
@@ -42,6 +42,9 @@ program::program(clover::context &ctx,
 
 void
 program::build(const ref_vector<device> &devs, const char *opts) {
+   if (_cl_kernel_ref_count.size())
+      throw error(CL_INVALID_OPERATION);
+
    if (has_source) {
       _devices = devs;
 
@@ -110,3 +113,14 @@ program::symbols() const {
 
    return _binaries.begin()->second.syms;
 }
+
+void program::ref_kernel(const std::string &name) {
+   ++_cl_kernel_ref_count[name];
+}
+
+void program::unref_kernel(const std::string &name) {
+   auto it = _cl_kernel_ref_count.find(name);
+   if (it != _cl_kernel_ref_count.end())
+      if (--(it->second) == 0)
+         _cl_kernel_ref_count.erase(it);
+}
diff --git a/src/gallium/state_trackers/clover/core/program.hpp 
b/src/gallium/state_trackers/clover/core/program.hpp
index 1081454..f9c91ed 100644
--- a/src/gallium/state_trackers/clover/core/program.hpp
+++ b/src/gallium/state_trackers/clover/core/program.hpp
@@ -60,6 +60,9 @@ namespace clover {
 
       const compat::vector<module::symbol> &symbols() const;
 
+      void ref_kernel(const std::string &name);
+      void unref_kernel(const std::string &name);
+
       const intrusive_ref<clover::context> context;
 
    private:
@@ -67,6 +70,7 @@ namespace clover {
       std::map<const device *, module> _binaries;
       std::map<const device *, std::string> _logs;
       std::map<const device *, std::string> _opts;
+      std::map<std::string, size_t> _cl_kernel_ref_count;
       std::string _source;
    };
 }
-- 
2.0.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to