/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2022 Baldur Karlsson
 * Copyright (c) 2014 Crytek
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

// when serialising out a multisampled texture to disk from the app we're capturing
// (or serialising it back in, for that matter), we copy each sample to a slice in a
// 2DArray texture, and vice-versa. These shaders do that copy as appropriate.

cbuffer msarraycopyconsts : register(b0)
{
  uint sampleCount;
  uint currentStencil;
  uint currentSample;
  uint currentSlice;
};

Texture2DMSArray<uint4, 2> sourceMS2 : register(t1);
Texture2DMSArray<uint4, 4> sourceMS4 : register(t2);
Texture2DMSArray<uint4, 8> sourceMS8 : register(t3);
Texture2DMSArray<uint4, 16> sourceMS16 : register(t4);
Texture2DMSArray<uint4, 32> sourceMS32 : register(t5);

uint4 RENDERDOC_CopyMSToArray(float4 pos : SV_Position) : SV_Target0
{
  uint3 srcCoord = uint3(pos.x, pos.y, currentSlice);

  if(sampleCount == 2)
  {
    return sourceMS2.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 4)
  {
    return sourceMS4.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 8)
  {
    return sourceMS8.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 16)
  {
    return sourceMS16.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 32)
  {
    return sourceMS32.Load(srcCoord, currentSample);
  }

  return 0;
}

Texture2DMSArray<float4, 2> sourceFloatMS2 : register(t1);
Texture2DMSArray<float4, 4> sourceFloatMS4 : register(t2);
Texture2DMSArray<float4, 8> sourceFloatMS8 : register(t3);
Texture2DMSArray<float4, 16> sourceFloatMS16 : register(t4);
Texture2DMSArray<float4, 32> sourceFloatMS32 : register(t5);

float4 RENDERDOC_FloatCopyMSToArray(float4 pos : SV_Position) : SV_Target0
{
  uint3 srcCoord = uint3(pos.x, pos.y, currentSlice);

  if(sampleCount == 2)
  {
    return sourceFloatMS2.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 4)
  {
    return sourceFloatMS4.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 8)
  {
    return sourceFloatMS8.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 16)
  {
    return sourceFloatMS16.Load(srcCoord, currentSample);
  }
  else if(sampleCount == 32)
  {
    return sourceFloatMS32.Load(srcCoord, currentSample);
  }

  return 0;
}

Texture2DMSArray<float2, 2> sourceDepthMS2 : register(t1);
Texture2DMSArray<float2, 4> sourceDepthMS4 : register(t2);
Texture2DMSArray<float2, 8> sourceDepthMS8 : register(t3);
Texture2DMSArray<float2, 16> sourceDepthMS16 : register(t4);
Texture2DMSArray<float2, 32> sourceDepthMS32 : register(t5);

Texture2DMSArray<uint2, 2> sourceStencilMS2 : register(t11);
Texture2DMSArray<uint2, 4> sourceStencilMS4 : register(t12);
Texture2DMSArray<uint2, 8> sourceStencilMS8 : register(t13);
Texture2DMSArray<uint2, 16> sourceStencilMS16 : register(t14);
Texture2DMSArray<uint2, 32> sourceStencilMS32 : register(t15);

float RENDERDOC_DepthCopyMSToArray(float4 pos : SV_Position) : SV_Depth
{
  uint3 srcCoord = uint3(pos.x, pos.y, currentSlice);

  if(currentStencil < 256)
  {
    if(sampleCount == 2)
    {
      if(sourceStencilMS2.Load(srcCoord, currentSample).y != currentStencil)
        discard;
    }
    else if(sampleCount == 4)
    {
      if(sourceStencilMS4.Load(srcCoord, currentSample).y != currentStencil)
        discard;
    }
    else if(sampleCount == 8)
    {
      if(sourceStencilMS8.Load(srcCoord, currentSample).y != currentStencil)
        discard;
    }
    else if(sampleCount == 16)
    {
      if(sourceStencilMS16.Load(srcCoord, currentSample).y != currentStencil)
        discard;
    }
    else if(sampleCount == 32)
    {
      if(sourceStencilMS32.Load(srcCoord, currentSample).y != currentStencil)
        discard;
    }
  }

  if(sampleCount == 2)
  {
    return sourceDepthMS2.Load(srcCoord, currentSample).x;
  }
  else if(sampleCount == 4)
  {
    return sourceDepthMS4.Load(srcCoord, currentSample).x;
  }
  else if(sampleCount == 8)
  {
    return sourceDepthMS8.Load(srcCoord, currentSample).x;
  }
  else if(sampleCount == 16)
  {
    return sourceDepthMS16.Load(srcCoord, currentSample).x;
  }
  else if(sampleCount == 32)
  {
    return sourceDepthMS32.Load(srcCoord, currentSample).x;
  }

  return 0;
}

Texture2DArray<uint4> sourceArray : register(t1);

uint4 RENDERDOC_CopyArrayToMS(float4 pos
                              : SV_Position, uint curSample
                              : SV_SampleIndex)
    : SV_Target0
{
  uint4 srcCoord = uint4(pos.x, pos.y, currentSlice * sampleCount + curSample, 0);

  return sourceArray.Load(srcCoord);
}

Texture2DArray<float4> sourceFloatArray : register(t1);

float4 RENDERDOC_FloatCopyArrayToMS(float4 pos
                                    : SV_Position, uint curSample
                                    : SV_SampleIndex)
    : SV_Target0
{
  uint4 srcCoord = uint4(pos.x, pos.y, currentSlice * sampleCount + curSample, 0);

  return sourceFloatArray.Load(srcCoord);
}

Texture2DArray<float2> sourceDepthArray : register(t1);
Texture2DArray<uint2> sourceStencilArray : register(t11);

float RENDERDOC_DepthCopyArrayToMS(float4 pos
                                   : SV_Position, uint curSample
                                   : SV_SampleIndex)
    : SV_Depth
{
  uint4 srcCoord = uint4(pos.x, pos.y, currentSlice * sampleCount + curSample, 0);

  if(currentStencil < 1000)
  {
    if(sourceStencilArray.Load(srcCoord).y != currentStencil)
      discard;
  }

  return sourceDepthArray.Load(srcCoord).x;
}
