/* Copyright (c) 2018-2024 The Khronos Group Inc.
 * Copyright (c) 2018-2024 Valve Corporation
 * Copyright (c) 2018-2024 LunarG, Inc.
 *
 * 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 "gpu/core/gpuav.h"
#include "gpu/cmd_validation/gpuav_cmd_validation_common.h"
#include "gpu/resources/gpuav_state_trackers.h"
#include "gpu/shaders/gpuav_error_header.h"
#include "gpu/shaders/gpuav_shaders_constants.h"
#include "generated/cmd_validation_dispatch_comp.h"

namespace gpuav {

// See gpu/shaders/cmd_validation/dispatch.comp
constexpr uint32_t kPushConstantDWords = 4u;

struct SharedDispatchValidationResources final {
    VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
    VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
    VkPipeline pipeline = VK_NULL_HANDLE;
    VkShaderEXT shader_object = VK_NULL_HANDLE;
    VkDevice device = VK_NULL_HANDLE;

    SharedDispatchValidationResources(Validator &gpuav, VkDescriptorSetLayout error_output_desc_set, bool use_shader_objects,
                                      const Location &loc)
        : device(gpuav.device) {
        VkResult result = VK_SUCCESS;
        std::vector<VkDescriptorSetLayoutBinding> bindings = {
            {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},  // indirect buffer
        };

        VkDescriptorSetLayoutCreateInfo ds_layout_ci = vku::InitStructHelper();
        ds_layout_ci.bindingCount = static_cast<uint32_t>(bindings.size());
        ds_layout_ci.pBindings = bindings.data();
        result = DispatchCreateDescriptorSetLayout(device, &ds_layout_ci, nullptr, &ds_layout);
        if (result != VK_SUCCESS) {
            gpuav.InternalError(device, loc, "Unable to create descriptor set layout.");
            return;
        }

        VkPushConstantRange push_constant_range = {};
        push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
        push_constant_range.offset = 0;
        push_constant_range.size = kPushConstantDWords * sizeof(uint32_t);

        std::array<VkDescriptorSetLayout, 2> set_layouts = {{error_output_desc_set, ds_layout}};
        VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper();
        pipeline_layout_ci.pushConstantRangeCount = 1;
        pipeline_layout_ci.pPushConstantRanges = &push_constant_range;
        pipeline_layout_ci.setLayoutCount = static_cast<uint32_t>(set_layouts.size());
        pipeline_layout_ci.pSetLayouts = set_layouts.data();
        result = DispatchCreatePipelineLayout(device, &pipeline_layout_ci, nullptr, &pipeline_layout);
        if (result != VK_SUCCESS) {
            gpuav.InternalError(device, loc, "Unable to create pipeline layout.");
            return;
        }

        if (use_shader_objects) {
            VkShaderCreateInfoEXT shader_ci = vku::InitStructHelper();
            shader_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
            shader_ci.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT;
            shader_ci.codeSize = cmd_validation_dispatch_comp_size * sizeof(uint32_t);
            shader_ci.pCode = cmd_validation_dispatch_comp;
            shader_ci.pName = "main";
            shader_ci.setLayoutCount = pipeline_layout_ci.setLayoutCount;
            shader_ci.pSetLayouts = pipeline_layout_ci.pSetLayouts;
            shader_ci.pushConstantRangeCount = pipeline_layout_ci.pushConstantRangeCount;
            shader_ci.pPushConstantRanges = pipeline_layout_ci.pPushConstantRanges;
            result = DispatchCreateShadersEXT(device, 1u, &shader_ci, nullptr, &shader_object);
            if (result != VK_SUCCESS) {
                gpuav.InternalError(device, loc, "Unable to create shader object.");
                return;
            }
        }

        {
            VkShaderModuleCreateInfo shader_module_ci = vku::InitStructHelper();
            shader_module_ci.codeSize = cmd_validation_dispatch_comp_size * sizeof(uint32_t);
            shader_module_ci.pCode = cmd_validation_dispatch_comp;
            VkShaderModule validation_shader = VK_NULL_HANDLE;
            result = DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &validation_shader);
            if (result != VK_SUCCESS) {
                gpuav.InternalError(device, loc, "Unable to create shader module.");
                return;
            }

            // Create pipeline
            VkPipelineShaderStageCreateInfo pipeline_stage_ci = vku::InitStructHelper();
            pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
            pipeline_stage_ci.module = validation_shader;
            pipeline_stage_ci.pName = "main";

            VkComputePipelineCreateInfo pipeline_ci = vku::InitStructHelper();
            pipeline_ci.stage = pipeline_stage_ci;
            pipeline_ci.layout = pipeline_layout;

            result = DispatchCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr, &pipeline);

            DispatchDestroyShaderModule(device, validation_shader, nullptr);

            if (result != VK_SUCCESS) {
                gpuav.InternalError(device, loc, "Failed to create compute pipeline for dispatch validation.");
                return;
            }
        }
    }

    ~SharedDispatchValidationResources() {
        if (ds_layout != VK_NULL_HANDLE) {
            DispatchDestroyDescriptorSetLayout(device, ds_layout, nullptr);
            ds_layout = VK_NULL_HANDLE;
        }
        if (pipeline_layout != VK_NULL_HANDLE) {
            DispatchDestroyPipelineLayout(device, pipeline_layout, nullptr);
            pipeline_layout = VK_NULL_HANDLE;
        }
        if (pipeline != VK_NULL_HANDLE) {
            DispatchDestroyPipeline(device, pipeline, nullptr);
            pipeline = VK_NULL_HANDLE;
        }
        if (shader_object != VK_NULL_HANDLE) {
            DispatchDestroyShaderEXT(device, shader_object, nullptr);
            shader_object = VK_NULL_HANDLE;
        }
    }

    bool IsValid() const {
        return ds_layout != VK_NULL_HANDLE && pipeline_layout != VK_NULL_HANDLE &&
               (pipeline != VK_NULL_HANDLE || shader_object != VK_NULL_HANDLE) && device != VK_NULL_HANDLE;
    }
};

void InsertIndirectDispatchValidation(Validator &gpuav, const Location &loc, CommandBuffer &cb_state, VkBuffer indirect_buffer,
                                      VkDeviceSize indirect_offset) {
    if (!gpuav.gpuav_settings.validate_indirect_dispatches_buffers) {
        return;
    }

    // Insert a dispatch that can examine some device memory right before the dispatch we're validating
    //
    // NOTE that this validation does not attempt to abort invalid api calls as most other validation does. A crash
    // or DEVICE_LOST resulting from the invalid call will prevent preceding validation errors from being reported.

    const auto lv_bind_point = ConvertToLvlBindPoint(VK_PIPELINE_BIND_POINT_COMPUTE);
    auto const &last_bound = cb_state.lastBound[lv_bind_point];
    const auto *pipeline_state = last_bound.pipeline_state;
    const bool use_shader_objects = pipeline_state == nullptr;

    auto &shared_dispatch_resources = gpuav.shared_resources_manager.Get<SharedDispatchValidationResources>(
        gpuav, cb_state.GetErrorLoggingDescSetLayout(), use_shader_objects, loc);

    assert(shared_dispatch_resources.IsValid());
    if (!shared_dispatch_resources.IsValid()) {
        return;
    }

    VkDescriptorSet indirect_buffer_desc_set =
        cb_state.gpu_resources_manager.GetManagedDescriptorSet(shared_dispatch_resources.ds_layout);
    if (indirect_buffer_desc_set == VK_NULL_HANDLE) {
        gpuav.InternalError(cb_state.VkHandle(), loc, "Unable to allocate descriptor set.");
        return;
    }

    VkDescriptorBufferInfo desc_buffer_info{};
    // Indirect buffer
    desc_buffer_info.buffer = indirect_buffer;
    desc_buffer_info.offset = 0;
    desc_buffer_info.range = VK_WHOLE_SIZE;

    VkWriteDescriptorSet desc_write{};
    desc_write = vku::InitStructHelper();
    desc_write.dstBinding = 0;
    desc_write.descriptorCount = 1;
    desc_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
    desc_write.pBufferInfo = &desc_buffer_info;
    desc_write.dstSet = indirect_buffer_desc_set;

    DispatchUpdateDescriptorSets(gpuav.device, 1, &desc_write, 0, nullptr);

    // Save current graphics pipeline state
    RestorablePipelineState restorable_state(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);

    // Insert diagnostic dispatch
    if (use_shader_objects) {
        VkShaderStageFlagBits stage = VK_SHADER_STAGE_COMPUTE_BIT;
        DispatchCmdBindShadersEXT(cb_state.VkHandle(), 1u, &stage, &shared_dispatch_resources.shader_object);
    } else {
        DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, shared_dispatch_resources.pipeline);
    }
    uint32_t push_constants[kPushConstantDWords] = {};
    push_constants[0] = gpuav.phys_dev_props.limits.maxComputeWorkGroupCount[0];
    push_constants[1] = gpuav.phys_dev_props.limits.maxComputeWorkGroupCount[1];
    push_constants[2] = gpuav.phys_dev_props.limits.maxComputeWorkGroupCount[2];
    push_constants[3] = static_cast<uint32_t>((indirect_offset / sizeof(uint32_t)));
    DispatchCmdPushConstants(cb_state.VkHandle(), shared_dispatch_resources.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
                             sizeof(push_constants), push_constants);
    BindErrorLoggingDescSet(gpuav, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, shared_dispatch_resources.pipeline_layout,
                            cb_state.compute_index, static_cast<uint32_t>(cb_state.per_command_error_loggers.size()));
    DispatchCmdBindDescriptorSets(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, shared_dispatch_resources.pipeline_layout,
                                  glsl::kDiagPerCmdDescriptorSet, 1, &indirect_buffer_desc_set, 0, nullptr);
    DispatchCmdDispatch(cb_state.VkHandle(), 1, 1, 1);

    CommandBuffer::ErrorLoggerFunc error_logger =
        [loc](Validator &gpuav, const CommandBuffer &, const uint32_t *error_record, const LogObjectList &objlist,
              const std::vector<std::string> &) {
            bool skip = false;
            using namespace glsl;

            if (error_record[kHeaderErrorGroupOffset] != kErrorGroupGpuPreDispatch) {
                return skip;
            }

            switch (error_record[kHeaderErrorSubCodeOffset]) {
                case kErrorSubCodePreDispatchCountLimitX: {
                    uint32_t count = error_record[kPreActionParamOffset_0];
                    skip |= gpuav.LogError("VUID-VkDispatchIndirectCommand-x-00417", objlist, loc,
                                           "Indirect dispatch VkDispatchIndirectCommand::x of %" PRIu32
                                           " would exceed maxComputeWorkGroupCount[0] limit of %" PRIu32 ".",
                                           count, gpuav.phys_dev_props.limits.maxComputeWorkGroupCount[0]);
                    break;
                }
                case kErrorSubCodePreDispatchCountLimitY: {
                    uint32_t count = error_record[kPreActionParamOffset_0];
                    skip |= gpuav.LogError("VUID-VkDispatchIndirectCommand-y-00418", objlist, loc,
                                           "Indirect dispatch VkDispatchIndirectCommand::y of %" PRIu32
                                           " would exceed maxComputeWorkGroupCount[1] limit of %" PRIu32 ".",
                                           count, gpuav.phys_dev_props.limits.maxComputeWorkGroupCount[1]);
                    break;
                }
                case kErrorSubCodePreDispatchCountLimitZ: {
                    uint32_t count = error_record[kPreActionParamOffset_0];
                    skip |= gpuav.LogError("VUID-VkDispatchIndirectCommand-z-00419", objlist, loc,
                                           "Indirect dispatch VkDispatchIndirectCommand::z of %" PRIu32
                                           " would exceed maxComputeWorkGroupCount[2] limit of %" PRIu32 ".",
                                           count, gpuav.phys_dev_props.limits.maxComputeWorkGroupCount[0]);
                    break;
                }
                default:
                    break;
            }

            return skip;
        };

    cb_state.per_command_error_loggers.emplace_back(std::move(error_logger));
}

}  // namespace gpuav
