Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Mon, 8 Oct 2018 21:46:00 +0000 (08:46 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 8 Oct 2018 21:46:00 +0000 (08:46 +1100)
1  2 
intern/cycles/device/device_cuda.cpp
tests/python/modules/render_report.py

index 2af8a9f48c87f06b3b08e941ffa26c6ea94e9840,5b46d5a507d44ab13afcbc72a7fbc7023acecd29..22b1bc493c848b67c4aa67773342cc99bdf1edd3
@@@ -1397,18 -1397,14 +1397,14 @@@ public
                int h = task->reconstruction_state.source_h;
                int stride = task->buffer.stride;
  
-               int shift_stride = stride*h;
+               int pass_stride = task->buffer.pass_stride;
                int num_shifts = (2*r+1)*(2*r+1);
-               int mem_size = sizeof(float)*shift_stride*num_shifts;
-               device_only_memory<uchar> temporary_mem(this, "Denoising temporary_mem");
-               temporary_mem.alloc_to_device(2*mem_size);
  
                if(have_error())
                        return false;
  
-               CUdeviceptr difference     = cuda_device_ptr(temporary_mem.device_pointer);
-               CUdeviceptr blurDifference = difference + mem_size;
+               CUdeviceptr difference     = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
+               CUdeviceptr blurDifference = difference + sizeof(float)*pass_stride*num_shifts;
  
                {
                        CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian;
                                             task->reconstruction_state.source_w * task->reconstruction_state.source_h,
                                             num_shifts);
  
-                       void *calc_difference_args[] = {&color_ptr, &color_variance_ptr, &difference, &w, &h, &stride, &shift_stride, &r, &task->buffer.pass_stride, &a, &k_2};
-                       void *blur_args[]            = {&difference, &blurDifference, &w, &h, &stride, &shift_stride, &r, &f};
-                       void *calc_weight_args[]     = {&blurDifference, &difference, &w, &h, &stride, &shift_stride, &r, &f};
+                       void *calc_difference_args[] = {&color_ptr, &color_variance_ptr, &difference, &w, &h, &stride, &pass_stride, &r, &pass_stride, &a, &k_2};
+                       void *blur_args[]            = {&difference, &blurDifference, &w, &h, &stride, &pass_stride, &r, &f};
+                       void *calc_weight_args[]     = {&blurDifference, &difference, &w, &h, &stride, &pass_stride, &r, &f};
                        void *construct_gramian_args[] = {&blurDifference,
                                                          &task->buffer.mem.device_pointer,
                                                          &task->storage.transform.device_pointer,
                                                          &task->storage.XtWY.device_pointer,
                                                          &task->reconstruction_state.filter_window,
                                                          &w, &h, &stride,
-                                                         &shift_stride, &r,
-                                                         &f,
-                                                     &task->buffer.pass_stride};
+                                                         &pass_stride, &r,
+                                                         &f};
  
                        CUDA_LAUNCH_KERNEL_1D(cuNLMCalcDifference, calc_difference_args);
                        CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
                        CUDA_LAUNCH_KERNEL_1D(cuNLMConstructGramian, construct_gramian_args);
                }
  
-               temporary_mem.free();
                {
                        CUfunction cuFinalize;
                        cuda_assert(cuModuleGetFunction(&cuFinalize, cuFilterModule, "kernel_cuda_filter_finalize"));
                glGenTextures(1, &pmem.cuTexId);
                glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
                if(mem.data_type == TYPE_HALF)
 -                      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
 +                      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
                else
                        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, pmem.w, pmem.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                }
        }
  
 -      void draw_pixels(device_memory& mem, int y, int w, int h, int dx, int dy, int width, int height, bool transparent,
 +      void draw_pixels(
 +          device_memory& mem, int y,
 +          int w, int h, int width, int height,
 +          int dx, int dy, int dw, int dh, bool transparent,
                const DeviceDrawParams &draw_params)
        {
                assert(mem.type == MEM_PIXELS);
  
                if(!background) {
 +                      const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL);
                        PixelMem pmem = pixel_mem_map[mem.device_pointer];
                        float *vpointer;
  
  
                        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
                        glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
 -                      if(mem.data_type == TYPE_HALF)
 +                      if(mem.data_type == TYPE_HALF) {
                                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_HALF_FLOAT, (void*)offset);
 -                      else
 +                      }
 +                      else {
                                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)offset);
 +                      }
                        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  
 -                      glEnable(GL_TEXTURE_2D);
 -
                        if(transparent) {
                                glEnable(GL_BLEND);
                                glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
                        }
  
 -                      glColor3f(1.0f, 1.0f, 1.0f);
 -
 -                      if(draw_params.bind_display_space_shader_cb) {
 +                      GLint shader_program;
 +                      if(use_fallback_shader) {
 +                              if(!bind_fallback_display_space_shader(dw, dh)) {
 +                                      return;
 +                              }
 +                              shader_program = fallback_shader_program;
 +                      }
 +                      else {
                                draw_params.bind_display_space_shader_cb();
 +                              glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program);
                        }
  
 -                      if(!vertex_buffer)
 +                      if(!vertex_buffer) {
                                glGenBuffers(1, &vertex_buffer);
 +                      }
  
                        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
                        /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
                                glUnmapBuffer(GL_ARRAY_BUFFER);
                        }
  
 -                      glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
 -                      glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)NULL + 2 * sizeof(float));
 +                      GLuint vertex_array_object;
 +                      GLuint position_attribute, texcoord_attribute;
  
 -                      glEnableClientState(GL_VERTEX_ARRAY);
 -                      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 +                      glGenVertexArrays(1, &vertex_array_object);
 +                      glBindVertexArray(vertex_array_object);
  
 -                      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 +                      texcoord_attribute = glGetAttribLocation(shader_program, "texCoord");
 +                      position_attribute = glGetAttribLocation(shader_program, "pos");
  
 -                      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 -                      glDisableClientState(GL_VERTEX_ARRAY);
 +                      glEnableVertexAttribArray(texcoord_attribute);
 +                      glEnableVertexAttribArray(position_attribute);
  
 -                      glBindBuffer(GL_ARRAY_BUFFER, 0);
 +                      glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
 +                      glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)(sizeof(float) * 2));
 +
 +                      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  
 -                      if(draw_params.unbind_display_space_shader_cb) {
 +                      if(use_fallback_shader) {
 +                              glUseProgram(0);
 +                      }
 +                      else {
                                draw_params.unbind_display_space_shader_cb();
                        }
  
 -                      if(transparent)
 +                      if(transparent) {
                                glDisable(GL_BLEND);
 +                      }
  
                        glBindTexture(GL_TEXTURE_2D, 0);
 -                      glDisable(GL_TEXTURE_2D);
  
                        return;
                }
  
 -              Device::draw_pixels(mem, y, w, h, dx, dy, width, height, transparent, draw_params);
 +              Device::draw_pixels(mem, y, w, h, width, height, dx, dy, dw, dh, transparent, draw_params);
        }
  
        void thread_run(DeviceTask *task)
index 8deed25e8543eda5e2d4cb9564b86c08c4a326b3,ed46abb4b63d61227c912f723879fa35c27672b1..9cff85f3dfa83303ac2c9c0921eb7a90174ee08e
@@@ -63,11 -63,11 +63,11 @@@ def test_get_name(filepath)
      return os.path.splitext(filename)[0]
  
  
 -def test_get_images(output_dir, filepath):
 +def test_get_images(output_dir, filepath, reference_dir):
      testname = test_get_name(filepath)
      dirpath = os.path.dirname(filepath)
  
 -    old_dirpath = os.path.join(dirpath, "reference_renders")
 +    old_dirpath = os.path.join(dirpath, reference_dir)
      old_img = os.path.join(old_dirpath, testname + ".png")
  
      ref_dirpath = os.path.join(output_dir, os.path.basename(dirpath), "ref")
@@@ -94,23 -94,18 +94,23 @@@ class Report
      __slots__ = (
          'title',
          'output_dir',
 +        'reference_dir',
          'idiff',
          'pixelated',
          'verbose',
          'update',
          'failed_tests',
 -        'passed_tests'
 +        'passed_tests',
 +        'compare_tests',
 +        'compare_engines'
      )
  
      def __init__(self, title, output_dir, idiff):
          self.title = title
          self.output_dir = output_dir
 +        self.reference_dir = 'reference_renders'
          self.idiff = idiff
 +        self.compare_engines = None
  
          self.pixelated = False
          self.verbose = os.environ.get("BLENDER_VERBOSE") is not None
  
          self.failed_tests = ""
          self.passed_tests = ""
 +        self.compare_tests = ""
  
          if not os.path.exists(output_dir):
              os.makedirs(output_dir)
      def set_pixelated(self, pixelated):
          self.pixelated = pixelated
  
 +    def set_reference_dir(self, reference_dir):
 +        self.reference_dir = reference_dir
 +
 +    def set_compare_engines(self, engine, other_engine):
 +        self.compare_engines = (engine, other_engine)
 +
      def run(self, dirpath, render_cb):
          # Run tests and output report.
          dirname = os.path.basename(dirpath)
          ok = self._run_all_tests(dirname, dirpath, render_cb)
 -        self._write_html(dirname)
 +        self._write_data(dirname)
 +        self._write_html()
 +        if self.compare_engines:
 +            self._write_html(comparison=True)
          return ok
  
 -    def _write_html(self, dirname):
 +    def _write_data(self, dirname):
          # Write intermediate data for single test.
          outdir = os.path.join(self.output_dir, dirname)
          if not os.path.exists(outdir):
          filepath = os.path.join(outdir, "passed.data")
          pathlib.Path(filepath).write_text(self.passed_tests)
  
 +        if self.compare_engines:
 +            filepath = os.path.join(outdir, "compare.data")
 +            pathlib.Path(filepath).write_text(self.compare_tests)
 +
 +    def _write_html(self, comparison=False):
          # Gather intermediate data for all tests.
 -        failed_data = sorted(glob.glob(os.path.join(self.output_dir, "*/failed.data")))
 -        passed_data = sorted(glob.glob(os.path.join(self.output_dir, "*/passed.data")))
 +        if comparison:
 +            failed_data = []
 +            passed_data = sorted(glob.glob(os.path.join(self.output_dir, "*/compare.data")))
 +        else:
 +            failed_data = sorted(glob.glob(os.path.join(self.output_dir, "*/failed.data")))
 +            passed_data = sorted(glob.glob(os.path.join(self.output_dir, "*/passed.data")))
  
          failed_tests = ""
          passed_tests = ""
          else:
              message = ""
  
 +        if comparison:
 +            title = "Render Test Compare"
 +            columns_html = "<tr><th>Name</th><th>%s</th><th>%s</th>" % self.compare_engines
 +        else:
 +            title = self.title
 +            columns_html = "<tr><th>Name</th><th>New</th><th>Reference</th><th>Diff</th>"
 +
          html = """
  <html>
  <head>
          <br/>
          <table class="table table-striped">
              <thead class="thead-default">
 -                <tr><th>Name</th><th>New</th><th>Reference</th><th>Diff</th>
 +                {columns_html}
              </thead>
              {tests_html}
          </table>
      </div>
  </body>
  </html>
 -            """ . format(title=self.title,
 +            """ . format(title=title,
                           message=message,
                           image_rendering=image_rendering,
 -                         tests_html=tests_html)
 +                         tests_html=tests_html,
 +                         columns_html=columns_html)
  
 -        filepath = os.path.join(self.output_dir, "report.html")
 +        filename = "report.html" if not comparison else "compare.html"
 +        filepath = os.path.join(self.output_dir, filename)
          pathlib.Path(filepath).write_text(html)
  
          print_message("Report saved to: " + pathlib.Path(filepath).as_uri())
          name = test_get_name(filepath)
          name = name.replace('_', ' ')
  
 -        old_img, ref_img, new_img, diff_img = test_get_images(self.output_dir, filepath)
 +        old_img, ref_img, new_img, diff_img = test_get_images(self.output_dir, filepath, self.reference_dir)
  
          status = error if error else ""
          tr_style = """ style="background-color: #f99;" """ if error else ""
          else:
              self.passed_tests += test_html
  
 +        if self.compare_engines:
 +            ref_url = os.path.join("..", self.compare_engines[1], new_url)
 +
 +            test_html = """
 +                <tr{tr_style}>
 +                    <td><b>{name}</b><br/>{testname}<br/>{status}</td>
 +                    <td><img src="{new_url}" onmouseover="this.src='{ref_url}';" onmouseout="this.src='{new_url}';" class="render"></td>
 +                    <td><img src="{ref_url}" onmouseover="this.src='{new_url}';" onmouseout="this.src='{ref_url}';" class="render"></td>
 +                </tr>""" . format(tr_style=tr_style,
 +                                  name=name,
 +                                  testname=testname,
 +                                  status=status,
 +                                  new_url=new_url,
 +                                  ref_url=ref_url)
 +
 +            self.compare_tests += test_html
 +
      def _diff_output(self, filepath, tmp_filepath):
 -        old_img, ref_img, new_img, diff_img = test_get_images(self.output_dir, filepath)
 +        old_img, ref_img, new_img, diff_img = test_get_images(self.output_dir, filepath, self.reference_dir)
  
          # Create reference render directory.
          old_dirpath = os.path.dirname(old_img)
          testname = test_get_name(filepath)
          print_message(testname, 'SUCCESS', 'RUN')
          time_start = time.time()
-         tmp_filepath = os.path.join(self.output_dir, "tmp")
+         tmp_filepath = os.path.join(self.output_dir, "tmp_" + testname)
  
          error = render_cb(filepath, tmp_filepath)
          status = "FAIL"