/*
 * MVKRenderPass.h
 *
 * Copyright (c) 2015-2021 The Brenwill Workshop Ltd. (http://www.brenwill.com)
 *
 * 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.
 */

#pragma once

#include "MVKDevice.h"
#include "MVKSmallVector.h"

#import <Metal/Metal.h>

class MVKRenderPass;
class MVKFramebuffer;
class MVKCommandEncoder;


// Parameters to define the sizing of inline collections
const static uint32_t kMVKDefaultAttachmentCount = 8;

/** Collection of attachment clears . */
typedef MVKSmallVector<VkClearAttachment, kMVKDefaultAttachmentCount> MVKClearAttachments;

#pragma mark -
#pragma mark MVKRenderSubpass

/** Represents a Vulkan render subpass. */
class MVKRenderSubpass : public MVKBaseObject {

public:


	/** Returns the Vulkan API opaque object controlling this object. */
	MVKVulkanAPIObject* getVulkanAPIObject() override;

	/** Returns the parent render pass of this subpass. */
	inline MVKRenderPass* getRenderPass() { return _renderPass; }

	/** Returns the index of this subpass in its parent render pass. */
	inline uint32_t getSubpassIndex() { return _subpassIndex; }

	/** Returns the number of color attachments, which may be zero for depth-only rendering. */
	inline uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }

	/** Returns the format of the color attachment at the specified index. */
	VkFormat getColorAttachmentFormat(uint32_t colorAttIdx);

	/** Returns whether or not the color attachment at the specified index is being used. */
	bool isColorAttachmentUsed(uint32_t colorAttIdx);

	/** Returns the format of the depth/stencil attachment. */
	VkFormat getDepthStencilFormat();

	/** Returns the Vulkan sample count of the attachments used in this subpass. */
	VkSampleCountFlagBits getSampleCount();

	/** Sets the default sample count for when there are no attachments used in this subpass. */
	void setDefaultSampleCount(VkSampleCountFlagBits count) { _defaultSampleCount = count; }

	/** Returns whether or not this is a multiview subpass. */
	bool isMultiview() const { return _viewMask != 0; }

	/** Returns the total number of views to be rendered. */
	inline uint32_t getViewCount() const { return __builtin_popcount(_viewMask); }

	/** Returns the number of Metal render passes needed to render all views. */
	uint32_t getMultiviewMetalPassCount() const;

	/** Returns the first view to be rendered in the given multiview pass. */
	uint32_t getFirstViewIndexInMetalPass(uint32_t passIdx) const;

	/** Returns the number of views to be rendered in the given multiview pass. */
	uint32_t getViewCountInMetalPass(uint32_t passIdx) const;

	/** Returns the number of views to be rendered in all multiview passes up to the given one. */
	uint32_t getViewCountUpToMetalPass(uint32_t passIdx) const;

	/** 
	 * Populates the specified Metal MTLRenderPassDescriptor with content from this
	 * instance, the specified framebuffer, and the specified array of clear values
	 * for the specified multiview pass.
	 */
	void populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc,
										 uint32_t passIdx,
										 VkExtent2D framebufferExtent,
										 uint32_t framebufferLayerCount,
										 const MVKArrayRef<MVKImageView*>& attachments,
										 const MVKArrayRef<VkClearValue>& clearValues,
										 bool isRenderingEntireAttachment,
                                         bool loadOverride = false);

	/**
	 * Populates the specified vector with the attachments that need to be cleared
	 * when the render area is smaller than the full framebuffer size.
	 */
	void populateClearAttachments(MVKClearAttachments& clearAtts,
								  const MVKArrayRef<VkClearValue>& clearValues);

	/**
	 * Populates the specified vector with VkClearRects for clearing views of a specified multiview
	 * attachment on first use, when the render area is smaller than the full framebuffer size
	 * and/or not all views used in this subpass need to be cleared.
	 */
	void populateMultiviewClearRects(MVKSmallVector<VkClearRect, 1>& clearRects,
									 MVKCommandEncoder* cmdEncoder,
									 uint32_t caIdx, VkImageAspectFlags aspectMask);

	/** If a render encoder is active, sets the store actions for all attachments to it. */
	void encodeStoreActions(MVKCommandEncoder* cmdEncoder,
							bool isRenderingEntireAttachment,
							const MVKArrayRef<MVKImageView*>& attachments,
							bool storeOverride = false);

	/** Constructs an instance for the specified parent renderpass. */
	MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription* pCreateInfo,
					 const VkRenderPassInputAttachmentAspectCreateInfo* pInputAspects,
					 uint32_t viewMask);

	/** Constructs an instance for the specified parent renderpass. */
	MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription2* pCreateInfo);

private:

	friend class MVKRenderPass;
	friend class MVKRenderPassAttachment;

	uint32_t getViewMaskGroupForMetalPass(uint32_t passIdx);
	MVKMTLFmtCaps getRequiredFormatCapabilitiesForAttachmentAt(uint32_t rpAttIdx);

	MVKRenderPass* _renderPass;
	uint32_t _subpassIndex;
	uint32_t _viewMask;
	MVKSmallVector<VkAttachmentReference2, kMVKDefaultAttachmentCount> _inputAttachments;
	MVKSmallVector<VkAttachmentReference2, kMVKDefaultAttachmentCount> _colorAttachments;
	MVKSmallVector<VkAttachmentReference2, kMVKDefaultAttachmentCount> _resolveAttachments;
	MVKSmallVector<uint32_t, kMVKDefaultAttachmentCount> _preserveAttachments;
	VkAttachmentReference2 _depthStencilAttachment;
	VkAttachmentReference2 _depthStencilResolveAttachment;
	VkResolveModeFlagBits _depthResolveMode = VK_RESOLVE_MODE_NONE;
	VkResolveModeFlagBits _stencilResolveMode = VK_RESOLVE_MODE_NONE;
	id<MTLTexture> _mtlDummyTex = nil;
	VkSampleCountFlagBits _defaultSampleCount = VK_SAMPLE_COUNT_1_BIT;
};


#pragma mark -
#pragma mark MVKRenderPassAttachment

/** Represents an attachment within a Vulkan render pass. */
class MVKRenderPassAttachment : public MVKBaseObject {

public:

	/** Returns the Vulkan API opaque object controlling this object. */
	MVKVulkanAPIObject* getVulkanAPIObject() override;

    /** Returns the Vulkan format of this attachment. */
    VkFormat getFormat();

	/** Returns the Vulkan sample count of this attachment. */
	VkSampleCountFlagBits getSampleCount();

    /**
     * Populates the specified Metal color attachment description with the load and store actions for
     * the specified render subpass, and returns whether the load action will clear the attachment.
     */
    bool populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc,
                                                   MVKRenderSubpass* subpass,
                                                   bool isRenderingEntireAttachment,
												   bool isMemorylessAttachment,
                                                   bool hasResolveAttachment,
                                                   bool isStencil,
                                                   bool loadOverride = false);

	/** If a render encoder is active, sets the store action for this attachment to it. */
	void encodeStoreAction(MVKCommandEncoder* cmdEncoder,
						   MVKRenderSubpass* subpass,
						   bool isRenderingEntireAttachment,
						   bool isMemorylessAttachment,
						   bool hasResolveAttachment,
						   uint32_t caIdx,
					   	   bool isStencil,
						   bool storeOverride = false);

	/** Populates the specified vector with VkClearRects for clearing views of a multiview attachment on first use. */
	void populateMultiviewClearRects(MVKSmallVector<VkClearRect, 1>& clearRects, MVKCommandEncoder* cmdEncoder);

    /** Returns whether this attachment should be cleared in the subpass. */
    bool shouldUseClearAttachment(MVKRenderSubpass* subpass);

    /** If this is a depth attachment, the stencil load op may be different than the depth load op. */
	VkAttachmentLoadOp getAttachmentStencilLoadOp() const;

	/** Constructs an instance for the specified parent renderpass. */
	MVKRenderPassAttachment(MVKRenderPass* renderPass,
							const VkAttachmentDescription* pCreateInfo);

	/** Constructs an instance for the specified parent renderpass. */
	MVKRenderPassAttachment(MVKRenderPass* renderPass,
							const VkAttachmentDescription2* pCreateInfo);

protected:
	bool isFirstUseOfAttachment(MVKRenderSubpass* subpass);
	bool isLastUseOfAttachment(MVKRenderSubpass* subpass);
	MTLStoreAction getMTLStoreAction(MVKRenderSubpass* subpass,
									 bool isRenderingEntireAttachment,
									 bool isMemorylessAttachment,
									 bool hasResolveAttachment,
									 bool isStencil,
									 bool storeOverride);
	void validateFormat();

	VkAttachmentDescription2 _info;
	MVKRenderPass* _renderPass;
	uint32_t _attachmentIndex;
	uint32_t _firstUseSubpassIdx;
	uint32_t _lastUseSubpassIdx;
	MVKSmallVector<uint32_t> _firstUseViewMasks;
	MVKSmallVector<uint32_t> _lastUseViewMasks;
};


#pragma mark -
#pragma mark MVKRenderPass

/** Represents a Vulkan render pass. */
class MVKRenderPass : public MVKVulkanAPIDeviceObject {

public:

	/** Returns the Vulkan type of this object. */
	VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_RENDER_PASS; }

	/** Returns the debug report object type of this object. */
	VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT; }

    /** Returns the granularity of the render area of this instance.  */
    VkExtent2D getRenderAreaGranularity();

	/** Returns the format of the color attachment at the specified index. */
	MVKRenderSubpass* getSubpass(uint32_t subpassIndex);

	/** Returns whether or not this render pass is a multiview render pass. */
	bool isMultiview() const;

	/** Constructs an instance for the specified device. */
	MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo* pCreateInfo);

	/** Constructs an instance for the specified device. */
	MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo2* pCreateInfo);

protected:
	friend class MVKRenderSubpass;
	friend class MVKRenderPassAttachment;

	void propagateDebugName() override {}

	MVKSmallVector<MVKRenderPassAttachment> _attachments;
	MVKSmallVector<MVKRenderSubpass> _subpasses;
	MVKSmallVector<VkSubpassDependency2> _subpassDependencies;

};

