/*
 * Copyright 2020 Google LLC
 *
 */

/*
 * Copyright (c) 2020, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include "dx/types.h"
#include "dx/av1_core.h"
#include "dx/av1_memory.h"
#include "dx/av1_compute.h"
#include "av1\common\scan.h"
#include "av1\common\idct.h"

struct cb_sort_data {
  int count;
  int src_offset;
  int reserved[2];
  int offsets[20][4];
};

struct idct_frame_data {
  int planes[3][4];
  int bitdepth;
};

void av1_idct_run(Av1Core *dec) {
  av1_frame_thread_data *td = dec->curr_frame_data;

  const int tile_count = td->tile_count;
  int offset = 0;
  for (int i = 0; i <= TX_SIZES_ALL + 1; ++i) {
    for (int t = 0; t < tile_count; ++t) {
      int count = td->tile_data[t].idct_blocks_sizes[i];
      td->tile_data[t].idct_blocks_sizes[i] = offset;
      offset += count;
    }
  }

  ComputeCommandBuffer *cb = &td->command_buffer;
  Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> command_list = dec->compute.command_list;
  ComputeShader *shader = &dec->shader_lib->shader_fill_buffer;

  command_list->SetComputeRootSignature(shader->signaturePtr.Get());
  command_list->SetPipelineState(shader->pso.Get());
  command_list->SetComputeRootUnorderedAccessView(0, dec->idct_residuals->dev->GetGPUVirtualAddress());
  int value[2];
  value[0] = static_cast<int>(dec->idct_residuals->size >> 4);
  value[1] = 0;
  command_list->SetComputeRoot32BitConstants(1, 2, value, 0);
  command_list->Dispatch((value[0] + 63) / 64, 1, 1);

  shader = &dec->shader_lib->shader_idct_sort;
  command_list->SetComputeRootSignature(shader->signaturePtr.Get());
  command_list->SetPipelineState(shader->pso.Get());
  command_list->SetComputeRootShaderResourceView(0, td->idct_blocks_unordered->dev->GetGPUVirtualAddress());
  command_list->SetComputeRootUnorderedAccessView(1, dec->idct_blocks->dev->GetGPUVirtualAddress());
  for (int t = 0; t < tile_count; ++t) {
    ConstantBufferObject cbo = cb->Alloc(sizeof(cb_sort_data));
    cb_sort_data *sort_data = reinterpret_cast<cb_sort_data *>(cbo.host_ptr);

    // av1_tile_thread_data * thr = td->thread_data + thread;
    av1_tile_data *tile = td->tile_data + t;
    for (int i = 0; i < TX_SIZES_ALL + 1; ++i) {
      sort_data->offsets[i][0] = tile->idct_blocks_sizes[i];
    }
    sort_data->count = tile->idct_blocks_ptr;
    sort_data->src_offset = tile->blocks_offset;
    if (tile->idct_blocks_ptr) {
      command_list->SetComputeRootConstantBufferView(2, cbo.dev_address);
      command_list->Dispatch((tile->idct_blocks_ptr + 63) / 64, 1, 1);
    }
  }

  D3D12_RESOURCE_BARRIER barriers[] = {CD3DX12_RESOURCE_BARRIER::UAV(dec->idct_blocks->dev),
                                       CD3DX12_RESOURCE_BARRIER::UAV(dec->idct_residuals->dev)};
  command_list->ResourceBarrier(2, barriers);
  ConstantBufferObject cbo = cb->Alloc(sizeof(idct_frame_data));
  idct_frame_data *data = reinterpret_cast<idct_frame_data *>(cbo.host_ptr);
  data->planes[0][0] = td->frame_buffer->planes[0].res_stride;
  data->planes[0][1] = td->frame_buffer->planes[0].res_offset;
  data->planes[1][0] = td->frame_buffer->planes[1].res_stride;
  data->planes[1][1] = td->frame_buffer->planes[1].res_offset;
  data->planes[2][0] = td->frame_buffer->planes[2].res_stride;
  data->planes[2][1] = td->frame_buffer->planes[2].res_offset;
  data->bitdepth = td->bitdepth;
  av1_tile_data *tdata = td->tile_data;

  command_list->SetComputeRootSignature(dec->shader_lib->sig_idct.Get());
  command_list->SetComputeRootShaderResourceView(0, dec->idct_coefs->dev->GetGPUVirtualAddress());
  command_list->SetComputeRootShaderResourceView(1, dec->idct_blocks->dev->GetGPUVirtualAddress());
  command_list->SetComputeRootUnorderedAccessView(2, dec->idct_residuals->dev->GetGPUVirtualAddress());
  command_list->SetComputeRootConstantBufferView(4, cbo.dev_address);
  for (int type = 0; type <= TX_SIZES_ALL; ++type) {
    int offset = tdata->idct_blocks_sizes[type];
    int count = tdata->idct_blocks_sizes[type + 1] - offset;
    if (count == 0) continue;

    const int tx_size = type == TX_SIZES_ALL ? TX_4X4 : type;
    const int block_w = tx_size_wide[tx_size];
    const int block_h = tx_size_high[tx_size];
    const int block_size = block_w * block_h;
    const int wi_per_block = AOMMIN(block_w, block_h);

    ConstantBufferObject scan_cbo = cb->Alloc(block_size * 3 * 4);
    int *gpu_scans = reinterpret_cast<int *>(scan_cbo.host_ptr);
    for (int s = 0; s < 3; ++s) {
      int *dst = gpu_scans + s * block_size;
      const int16_t *scan = av1_idct_scans[tx_size][s];
      if (block_w > 32) {
        for (int i = 0; i < 32 * block_h; ++i) {
          int s = scan[i];
          dst[i] = (s & 31) + (s / 32) * 64;
        }
      } else
        for (int i = 0; i < block_size; ++i) dst[i] = scan[i];
    }

    int const_inline[2];
    const_inline[0] = offset;
    const_inline[1] = wi_per_block * count;
    command_list->SetPipelineState(dec->shader_lib->shader_idct[type].pso.Get());
    command_list->SetComputeRootConstantBufferView(3, scan_cbo.dev_address);
    command_list->SetComputeRoot32BitConstants(5, 2, const_inline, 0);
    command_list->Dispatch((const_inline[1] + 63) / 64, 1, 1);
  }
  command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::UAV(dec->idct_residuals->dev));
}
