// Copyright 2018 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "common/Constants.h"

#include "dawn_native/ShaderModule.h"

#include "tests/unittests/validation/ValidationTest.h"

#include "utils/WGPUHelpers.h"

#include <sstream>

class ShaderModuleValidationTest : public ValidationTest {};

// Test case with a simpler shader that should successfully be created
TEST_F(ShaderModuleValidationTest, CreationSuccess) {
    const char* shader = R"(
                   OpCapability Shader
              %1 = OpExtInstImport "GLSL.std.450"
                   OpMemoryModel Logical GLSL450
                   OpEntryPoint Fragment %main "main" %fragColor
                   OpExecutionMode %main OriginUpperLeft
                   OpSource GLSL 450
                   OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
                   OpSourceExtension "GL_GOOGLE_include_directive"
                   OpName %main "main"
                   OpName %fragColor "fragColor"
                   OpDecorate %fragColor Location 0
           %void = OpTypeVoid
              %3 = OpTypeFunction %void
          %float = OpTypeFloat 32
        %v4float = OpTypeVector %float 4
    %_ptr_Output_v4float = OpTypePointer Output %v4float
      %fragColor = OpVariable %_ptr_Output_v4float Output
        %float_1 = OpConstant %float 1
        %float_0 = OpConstant %float 0
             %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
           %main = OpFunction %void None %3
              %5 = OpLabel
                   OpStore %fragColor %12
                   OpReturn
                   OpFunctionEnd)";

    utils::CreateShaderModuleFromASM(device, shader);
}

// Tests that if the output location exceeds kMaxColorAttachments the fragment shader will fail to
// be compiled.
TEST_F(ShaderModuleValidationTest, FragmentOutputLocationExceedsMaxColorAttachments) {
    std::ostringstream stream;
    stream << "[[stage(fragment)]] fn main() -> [[location(" << kMaxColorAttachments
           << R"()]]  vec4<f32> {
            return vec4<f32>(0.0, 1.0, 0.0, 1.0);
        })";
    ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, stream.str().c_str()));
}

// Test that it is invalid to create a shader module with no chained descriptor. (It must be
// WGSL or SPIRV, not empty)
TEST_F(ShaderModuleValidationTest, NoChainedDescriptor) {
    wgpu::ShaderModuleDescriptor desc = {};
    ASSERT_DEVICE_ERROR(device.CreateShaderModule(&desc));
}

// Test that it is not allowed to use combined texture and sampler.
TEST_F(ShaderModuleValidationTest, CombinedTextureAndSampler) {
    // SPIR-V ASM produced by glslang for the following fragment shader:
    //
    //   #version 450
    //   layout(set = 0, binding = 0) uniform sampler2D tex;
    //   void main () {}
    //
    // Note that the following defines an interface combined texture/sampler which is not allowed
    // in Dawn / WebGPU.
    //
    //   %8 = OpTypeSampledImage %7
    //   %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
    //   %tex = OpVariable %_ptr_UniformConstant_8 UniformConstant
    const char* shader = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main"
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 450
               OpName %main "main"
               OpName %tex "tex"
               OpDecorate %tex DescriptorSet 0
               OpDecorate %tex Binding 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
      %float = OpTypeFloat 32
          %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
          %8 = OpTypeSampledImage %7
%_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
        %tex = OpVariable %_ptr_UniformConstant_8 UniformConstant
       %main = OpFunction %void None %3
          %5 = OpLabel
               OpReturn
               OpFunctionEnd
        )";

    ASSERT_DEVICE_ERROR(utils::CreateShaderModuleFromASM(device, shader));
}

// Test that it is not allowed to declare a multisampled-array interface texture.
// TODO(enga): Also test multisampled cube, cube array, and 3D. These have no GLSL keywords.
TEST_F(ShaderModuleValidationTest, MultisampledArrayTexture) {
    // SPIR-V ASM produced by glslang for the following fragment shader:
    //
    //  #version 450
    //  layout(set=0, binding=0) uniform texture2DMSArray tex;
    //  void main () {}}
    //
    // Note that the following defines an interface array multisampled texture which is not allowed
    // in Dawn / WebGPU.
    //
    //  %7 = OpTypeImage %float 2D 0 1 1 1 Unknown
    //  %_ptr_UniformConstant_7 = OpTypePointer UniformConstant %7
    //  %tex = OpVariable %_ptr_UniformConstant_7 UniformConstant
    const char* shader = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %main "main"
               OpExecutionMode %main OriginUpperLeft
               OpSource GLSL 450
               OpName %main "main"
               OpName %tex "tex"
               OpDecorate %tex DescriptorSet 0
               OpDecorate %tex Binding 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
      %float = OpTypeFloat 32
          %7 = OpTypeImage %float 2D 0 1 1 1 Unknown
%_ptr_UniformConstant_7 = OpTypePointer UniformConstant %7
        %tex = OpVariable %_ptr_UniformConstant_7 UniformConstant
       %main = OpFunction %void None %3
          %5 = OpLabel
               OpReturn
               OpFunctionEnd
        )";

    ASSERT_DEVICE_ERROR(utils::CreateShaderModuleFromASM(device, shader));
}

// Tests that shader module compilation messages can be queried.
TEST_F(ShaderModuleValidationTest, GetCompilationMessages) {
    // This test works assuming ShaderModule is backed by a dawn::native::ShaderModuleBase, which
    // is not the case on the wire.
    DAWN_SKIP_TEST_IF(UsesWire());

    wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, R"(
        [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
            return vec4<f32>(0.0, 1.0, 0.0, 1.0);
        })");

    dawn::native::ShaderModuleBase* shaderModuleBase = dawn::native::FromAPI(shaderModule.Get());
    dawn::native::OwnedCompilationMessages* messages = shaderModuleBase->GetCompilationMessages();
    messages->ClearMessages();
    messages->AddMessageForTesting("Info Message");
    messages->AddMessageForTesting("Warning Message", wgpu::CompilationMessageType::Warning);
    messages->AddMessageForTesting("Error Message", wgpu::CompilationMessageType::Error, 3, 4);
    messages->AddMessageForTesting("Complete Message", wgpu::CompilationMessageType::Info, 3, 4, 5,
                                   6);

    auto callback = [](WGPUCompilationInfoRequestStatus status, const WGPUCompilationInfo* info,
                       void* userdata) {
        ASSERT_EQ(WGPUCompilationInfoRequestStatus_Success, status);
        ASSERT_NE(nullptr, info);
        ASSERT_EQ(4u, info->messageCount);

        const WGPUCompilationMessage* message = &info->messages[0];
        ASSERT_STREQ("Info Message", message->message);
        ASSERT_EQ(WGPUCompilationMessageType_Info, message->type);
        ASSERT_EQ(0u, message->lineNum);
        ASSERT_EQ(0u, message->linePos);

        message = &info->messages[1];
        ASSERT_STREQ("Warning Message", message->message);
        ASSERT_EQ(WGPUCompilationMessageType_Warning, message->type);
        ASSERT_EQ(0u, message->lineNum);
        ASSERT_EQ(0u, message->linePos);

        message = &info->messages[2];
        ASSERT_STREQ("Error Message", message->message);
        ASSERT_EQ(WGPUCompilationMessageType_Error, message->type);
        ASSERT_EQ(3u, message->lineNum);
        ASSERT_EQ(4u, message->linePos);

        message = &info->messages[3];
        ASSERT_STREQ("Complete Message", message->message);
        ASSERT_EQ(WGPUCompilationMessageType_Info, message->type);
        ASSERT_EQ(3u, message->lineNum);
        ASSERT_EQ(4u, message->linePos);
        ASSERT_EQ(5u, message->offset);
        ASSERT_EQ(6u, message->length);
    };

    shaderModule.GetCompilationInfo(callback, nullptr);
}

// Validate the maximum location of effective inter-stage variables cannot be greater than 14
// (kMaxInterStageShaderComponents / 4 - 1).
TEST_F(ShaderModuleValidationTest, MaximumShaderIOLocations) {
    auto generateShaderForTest = [](uint32_t maximumOutputLocation, wgpu::ShaderStage shaderStage) {
        std::ostringstream stream;
        stream << "struct ShaderIO {" << std::endl;
        for (uint32_t location = 1; location <= maximumOutputLocation; ++location) {
            stream << "[[location(" << location << ")]] var" << location << ": f32;" << std::endl;
        }
        switch (shaderStage) {
            case wgpu::ShaderStage::Vertex: {
                stream << R"(
                    [[builtin(position)]] pos: vec4<f32>;
                };
                [[stage(vertex)]] fn main() -> ShaderIO {
                    var shaderIO : ShaderIO;
                    shaderIO.pos = vec4<f32>(0.0, 0.0, 0.0, 1.0);
                    return shaderIO;
                 })";
            } break;

            case wgpu::ShaderStage::Fragment: {
                stream << R"(
                };
                [[stage(fragment)]] fn main(shaderIO: ShaderIO) -> [[location(0)]] vec4<f32> {
                    return vec4<f32>(0.0, 0.0, 0.0, 1.0);
                })";
            } break;

            case wgpu::ShaderStage::Compute:
            default:
                UNREACHABLE();
        }

        return stream.str();
    };

    constexpr uint32_t kMaxInterShaderIOLocation = kMaxInterStageShaderComponents / 4 - 1;

    // It is allowed to create a shader module with the maximum active vertex output location == 14;
    {
        std::string vertexShader =
            generateShaderForTest(kMaxInterShaderIOLocation, wgpu::ShaderStage::Vertex);
        utils::CreateShaderModule(device, vertexShader.c_str());
    }

    // It isn't allowed to create a shader module with the maximum active vertex output location >
    // 14;
    {
        std::string vertexShader =
            generateShaderForTest(kMaxInterShaderIOLocation + 1, wgpu::ShaderStage::Vertex);
        ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, vertexShader.c_str()));
    }

    // It is allowed to create a shader module with the maximum active fragment input location ==
    // 14;
    {
        std::string fragmentShader =
            generateShaderForTest(kMaxInterShaderIOLocation, wgpu::ShaderStage::Fragment);
        utils::CreateShaderModule(device, fragmentShader.c_str());
    }

    // It is allowed to create a shader module with the maximum active vertex output location > 14;
    {
        std::string fragmentShader =
            generateShaderForTest(kMaxInterShaderIOLocation + 1, wgpu::ShaderStage::Fragment);
        ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
    }
}

// Validate the maximum number of total inter-stage user-defined variable component count and
// built-in variables cannot exceed kMaxInterStageShaderComponents.
TEST_F(ShaderModuleValidationTest, MaximumInterStageShaderComponents) {
    auto generateShaderForTest = [](uint32_t totalUserDefinedInterStageShaderComponentCount,
                                    wgpu::ShaderStage shaderStage,
                                    const char* builtInDeclarations) {
        std::ostringstream stream;
        stream << "struct ShaderIO {" << std::endl << builtInDeclarations << std::endl;
        uint32_t vec4InputLocations = totalUserDefinedInterStageShaderComponentCount / 4;

        for (uint32_t location = 0; location < vec4InputLocations; ++location) {
            stream << "[[location(" << location << ")]] var" << location << ": vec4<f32>;"
                   << std::endl;
        }

        uint32_t lastComponentCount = totalUserDefinedInterStageShaderComponentCount % 4;
        if (lastComponentCount > 0) {
            stream << "[[location(" << vec4InputLocations << ")]] var" << vec4InputLocations
                   << ": ";
            if (lastComponentCount == 1) {
                stream << "f32;";
            } else {
                stream << " vec" << lastComponentCount << "<f32>;";
            }
            stream << std::endl;
        }

        switch (shaderStage) {
            case wgpu::ShaderStage::Vertex: {
                stream << R"(
                    [[builtin(position)]] pos: vec4<f32>;
                };
                [[stage(vertex)]] fn main() -> ShaderIO {
                    var shaderIO : ShaderIO;
                    shaderIO.pos = vec4<f32>(0.0, 0.0, 0.0, 1.0);
                    return shaderIO;
                 })";
            } break;

            case wgpu::ShaderStage::Fragment: {
                stream << R"(
                };
                [[stage(fragment)]] fn main(shaderIO: ShaderIO) -> [[location(0)]] vec4<f32> {
                    return vec4<f32>(0.0, 0.0, 0.0, 1.0);
                })";
            } break;

            case wgpu::ShaderStage::Compute:
            default:
                UNREACHABLE();
        }

        return stream.str();
    };

    // Verify when there is no input builtin variable in a fragment shader, the total user-defined
    // input component count must be less than kMaxInterStageShaderComponents.
    {
        constexpr uint32_t kInterStageShaderComponentCount = kMaxInterStageShaderComponents;
        std::string correctFragmentShader =
            generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Fragment, "");
        utils::CreateShaderModule(device, correctFragmentShader.c_str());

        std::string errorFragmentShader = generateShaderForTest(kInterStageShaderComponentCount + 1,
                                                                wgpu::ShaderStage::Fragment, "");
        ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, errorFragmentShader.c_str()));
    }

    // [[position]] should be counted into the maximum inter-stage component count.
    // Note that in vertex shader we always have [[position]] so we don't need to specify it
    // again in the parameter "builtInDeclarations" of generateShaderForTest().
    {
        constexpr uint32_t kInterStageShaderComponentCount = kMaxInterStageShaderComponents - 4;
        std::string vertexShader =
            generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Vertex, "");
        utils::CreateShaderModule(device, vertexShader.c_str());

        std::string fragmentShader =
            generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Fragment,
                                  "[[builtin(position)]] fragCoord: vec4<f32>;");
        utils::CreateShaderModule(device, fragmentShader.c_str());
    }

    {
        constexpr uint32_t kInterStageShaderComponentCount = kMaxInterStageShaderComponents - 3;
        std::string vertexShader =
            generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Vertex, "");
        ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, vertexShader.c_str()));

        std::string fragmentShader =
            generateShaderForTest(kInterStageShaderComponentCount, wgpu::ShaderStage::Fragment,
                                  "[[builtin(position)]] fragCoord: vec4<f32>;");
        ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
    }

    // [[front_facing]] should be counted into the maximum inter-stage component count.
    {
        const char* builtinDeclaration = "[[builtin(front_facing)]] frontFacing : bool;";

        {
            std::string fragmentShader =
                generateShaderForTest(kMaxInterStageShaderComponents - 1,
                                      wgpu::ShaderStage::Fragment, builtinDeclaration);
            utils::CreateShaderModule(device, fragmentShader.c_str());
        }

        {
            std::string fragmentShader = generateShaderForTest(
                kMaxInterStageShaderComponents, wgpu::ShaderStage::Fragment, builtinDeclaration);
            ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
        }
    }

    // [[sample_index]] should be counted into the maximum inter-stage component count.
    {
        const char* builtinDeclaration = "[[builtin(sample_index)]] sampleIndex: u32;";

        {
            std::string fragmentShader =
                generateShaderForTest(kMaxInterStageShaderComponents - 1,
                                      wgpu::ShaderStage::Fragment, builtinDeclaration);
            utils::CreateShaderModule(device, fragmentShader.c_str());
        }

        {
            std::string fragmentShader = generateShaderForTest(
                kMaxInterStageShaderComponents, wgpu::ShaderStage::Fragment, builtinDeclaration);
            ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
        }
    }

    // [[sample_mask]] should be counted into the maximum inter-stage component count.
    {
        const char* builtinDeclaration = "[[builtin(front_facing)]] frontFacing : bool;";

        {
            std::string fragmentShader =
                generateShaderForTest(kMaxInterStageShaderComponents - 1,
                                      wgpu::ShaderStage::Fragment, builtinDeclaration);
            utils::CreateShaderModule(device, fragmentShader.c_str());
        }

        {
            std::string fragmentShader = generateShaderForTest(
                kMaxInterStageShaderComponents, wgpu::ShaderStage::Fragment, builtinDeclaration);
            ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, fragmentShader.c_str()));
        }
    }
}

// Tests that we validate workgroup size limits.
TEST_F(ShaderModuleValidationTest, ComputeWorkgroupSizeLimits) {
    auto MakeShaderWithWorkgroupSize = [this](uint32_t x, uint32_t y, uint32_t z) {
        std::ostringstream ss;
        ss << "[[stage(compute), workgroup_size(" << x << "," << y << "," << z
           << ")]] fn main() {}";
        utils::CreateShaderModule(device, ss.str().c_str());
    };

    wgpu::Limits supportedLimits = GetSupportedLimits().limits;

    MakeShaderWithWorkgroupSize(1, 1, 1);
    MakeShaderWithWorkgroupSize(supportedLimits.maxComputeWorkgroupSizeX, 1, 1);
    MakeShaderWithWorkgroupSize(1, supportedLimits.maxComputeWorkgroupSizeY, 1);
    MakeShaderWithWorkgroupSize(1, 1, supportedLimits.maxComputeWorkgroupSizeZ);

    ASSERT_DEVICE_ERROR(
        MakeShaderWithWorkgroupSize(supportedLimits.maxComputeWorkgroupSizeX + 1, 1, 1));
    ASSERT_DEVICE_ERROR(
        MakeShaderWithWorkgroupSize(1, supportedLimits.maxComputeWorkgroupSizeY + 1, 1));
    ASSERT_DEVICE_ERROR(
        MakeShaderWithWorkgroupSize(1, 1, supportedLimits.maxComputeWorkgroupSizeZ + 1));

    // No individual dimension exceeds its limit, but the combined size should definitely exceed the
    // total invocation limit.
    ASSERT_DEVICE_ERROR(MakeShaderWithWorkgroupSize(supportedLimits.maxComputeWorkgroupSizeX,
                                                    supportedLimits.maxComputeWorkgroupSizeY,
                                                    supportedLimits.maxComputeWorkgroupSizeZ));
}

// Tests that we validate workgroup storage size limits.
TEST_F(ShaderModuleValidationTest, ComputeWorkgroupStorageSizeLimits) {
    wgpu::Limits supportedLimits = GetSupportedLimits().limits;

    constexpr uint32_t kVec4Size = 16;
    const uint32_t maxVec4Count = supportedLimits.maxComputeWorkgroupStorageSize / kVec4Size;
    constexpr uint32_t kMat4Size = 64;
    const uint32_t maxMat4Count = supportedLimits.maxComputeWorkgroupStorageSize / kMat4Size;

    auto MakeShaderWithWorkgroupStorage = [this](uint32_t vec4_count, uint32_t mat4_count) {
        std::ostringstream ss;
        std::ostringstream body;
        if (vec4_count > 0) {
            ss << "var<workgroup> vec4_data: array<vec4<f32>, " << vec4_count << ">;";
            body << "_ = vec4_data;";
        }
        if (mat4_count > 0) {
            ss << "var<workgroup> mat4_data: array<mat4x4<f32>, " << mat4_count << ">;";
            body << "_ = mat4_data;";
        }
        ss << "[[stage(compute), workgroup_size(1)]] fn main() { " << body.str() << " }";
        utils::CreateShaderModule(device, ss.str().c_str());
    };

    MakeShaderWithWorkgroupStorage(1, 1);
    MakeShaderWithWorkgroupStorage(maxVec4Count, 0);
    MakeShaderWithWorkgroupStorage(0, maxMat4Count);
    MakeShaderWithWorkgroupStorage(maxVec4Count - 4, 1);
    MakeShaderWithWorkgroupStorage(4, maxMat4Count - 1);
    ASSERT_DEVICE_ERROR(MakeShaderWithWorkgroupStorage(maxVec4Count + 1, 0));
    ASSERT_DEVICE_ERROR(MakeShaderWithWorkgroupStorage(maxVec4Count - 3, 1));
    ASSERT_DEVICE_ERROR(MakeShaderWithWorkgroupStorage(0, maxMat4Count + 1));
    ASSERT_DEVICE_ERROR(MakeShaderWithWorkgroupStorage(4, maxMat4Count));
}

// Test that numeric ID must be unique
TEST_F(ShaderModuleValidationTest, OverridableConstantsNumericIDConflicts) {
    ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, R"(
[[override(1234)]] let c0: u32;
[[override(1234)]] let c1: u32;

struct Buf {
    data : array<u32, 2>;
};

[[group(0), binding(0)]] var<storage, read_write> buf : Buf;

[[stage(compute), workgroup_size(1)]] fn main() {
    // make sure the overridable constants are not optimized out
    buf.data[0] = c0;
    buf.data[1] = c1;
})"));
}
