// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#ifndef VK_DESCRIPTOR_SET_LAYOUT_HPP_
#define VK_DESCRIPTOR_SET_LAYOUT_HPP_

#include "VkObject.hpp"

#include "Vulkan/VkSampler.hpp"
#include "Vulkan/VkImageView.hpp"
#include "Device/Sampler.hpp"

namespace vk
{

class DescriptorSet;

// TODO(b/129523279): Move to the Device or Pipeline layer.
struct alignas(16) SampledImageDescriptor
{
	void updateSampler(const vk::Sampler *sampler);

	// TODO(b/129523279): Minimize to the data actually needed.
	vk::Sampler sampler;

	uint32_t imageViewId;
	VkImageViewType type;
	VkFormat format;
	VkComponentMapping swizzle;
	alignas(16) sw::Texture texture;
	VkExtent3D extent; // Of base mip-level.
	int arrayLayers;
	int mipLevels;
	int sampleCount;
};

struct alignas(16) StorageImageDescriptor
{
	void *ptr;
	VkExtent3D extent;
	int rowPitchBytes;
	int slicePitchBytes;
	int samplePitchBytes;
	int arrayLayers;
	int sampleCount;
	int sizeInBytes;

	void *stencilPtr;
	int stencilRowPitchBytes;
	int stencilSlicePitchBytes;
	int stencilSamplePitchBytes;
};

struct alignas(16) BufferDescriptor
{
	void *ptr;
	int sizeInBytes;		// intended size of the bound region -- slides along with dynamic offsets
	int robustnessSize;		// total accessible size from static offset -- does not move with dynamic offset
};

class DescriptorSetLayout : public Object<DescriptorSetLayout, VkDescriptorSetLayout>
{
public:
	DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo, void* mem);
	void destroy(const VkAllocationCallbacks* pAllocator);

	static size_t ComputeRequiredAllocationSize(const VkDescriptorSetLayoutCreateInfo* pCreateInfo);

	static size_t GetDescriptorSize(VkDescriptorType type);
	static void WriteDescriptorSet(const VkWriteDescriptorSet& descriptorWrites);
	static void CopyDescriptorSet(const VkCopyDescriptorSet& descriptorCopies);

	static void WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptorUpdateTemplateEntry const &entry, char const *src);

	void initialize(VkDescriptorSet descriptorSet);

	// Returns the total size of the descriptor set in bytes.
	size_t getDescriptorSetAllocationSize() const;

	// Returns the number of bindings in the descriptor set.
	size_t getBindingCount() const;

	// Returns true iff the given binding exists.
	bool hasBinding(uint32_t binding) const;

	// Returns the byte offset from the base address of the descriptor set for
	// the given binding and array element within that binding.
	size_t getBindingOffset(uint32_t binding, size_t arrayElement) const;

	// Returns the stride of an array of descriptors
	size_t getBindingStride(uint32_t binding) const;

	// Returns the number of descriptors across all bindings that are dynamic
	// (see isBindingDynamic).
	uint32_t getDynamicDescriptorCount() const;

	// Returns the relative offset into the pipeline's dynamic offsets array for
	// the given binding. This offset should be added to the base offset
	// returned by PipelineLayout::getDynamicOffsetBase() to produce the
	// starting index for dynamic descriptors.
	uint32_t getDynamicDescriptorOffset(uint32_t binding) const;

	// Returns true if the given binding is of type:
	//  VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or
	//  VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
	bool isBindingDynamic(uint32_t binding) const;

	// Returns the VkDescriptorSetLayoutBinding for the given binding.
	VkDescriptorSetLayoutBinding const & getBindingLayout(uint32_t binding) const;

	uint8_t* getOffsetPointer(DescriptorSet *descriptorSet, uint32_t binding, uint32_t arrayElement, uint32_t count, size_t* typeSize) const;

private:
	size_t getDescriptorSetDataSize() const;
	uint32_t getBindingIndex(uint32_t binding) const;
	static bool isDynamic(VkDescriptorType type);

	VkDescriptorSetLayoutCreateFlags flags;
	uint32_t                         bindingCount;
	VkDescriptorSetLayoutBinding*    bindings;
	size_t*                          bindingOffsets;
};

static inline DescriptorSetLayout* Cast(VkDescriptorSetLayout object)
{
	return reinterpret_cast<DescriptorSetLayout*>(object.get());
}

} // namespace vk

#endif // VK_DESCRIPTOR_SET_LAYOUT_HPP_
