VkImageView initial implementation

Added VkImageView object.
Added "clear" function to illustrate the link between VkFramebuffer
attachments, VkImageView and VkImage, along with the minimal set of
class members to allows the function arguments to be used properly.

Bug b/119620767 b/119621736

Change-Id: I0e7e6017979960bacbdf888d632c83edda3483cf
Reviewed-on: https://swiftshader-review.googlesource.com/c/22668
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Vulkan/VkDestroy.h b/src/Vulkan/VkDestroy.h
index b627a3e..f147aab 100644
--- a/src/Vulkan/VkDestroy.h
+++ b/src/Vulkan/VkDestroy.h
@@ -22,6 +22,7 @@
 #include "VkFence.hpp"
 #include "VkFramebuffer.hpp"
 #include "VkImage.hpp"
+#include "VkImageView.hpp"
 #include "VkInstance.hpp"
 #include "VkPipeline.hpp"
 #include "VkPipelineCache.hpp"
diff --git a/src/Vulkan/VkFramebuffer.cpp b/src/Vulkan/VkFramebuffer.cpp
index e31e938..379ef09 100644
--- a/src/Vulkan/VkFramebuffer.cpp
+++ b/src/Vulkan/VkFramebuffer.cpp
@@ -13,21 +13,40 @@
 // limitations under the License.
 
 #include "VkFramebuffer.hpp"
+#include "VkImageView.hpp"
+#include <memory.h>
 
 namespace vk
 {
 
-Framebuffer::Framebuffer(const VkFramebufferCreateInfo* pCreateInfo, void* mem)
+Framebuffer::Framebuffer(const VkFramebufferCreateInfo* pCreateInfo, void* mem) :
+	attachmentCount(pCreateInfo->attachmentCount),
+	attachments(reinterpret_cast<ImageView**>(mem))
 {
+	for(uint32_t i = 0; i < attachmentCount; i++)
+	{
+		attachments[i] = Cast(pCreateInfo->pAttachments[i]);
+	}
 }
 
 void Framebuffer::destroy(const VkAllocationCallbacks* pAllocator)
 {
+	vk::deallocate(attachments, pAllocator);
+}
+
+void Framebuffer::clear(uint32_t clearValueCount, const VkClearValue* pClearValues, const VkRect2D& renderArea)
+{
+	ASSERT(clearValueCount >= attachmentCount);
+
+	for(uint32_t i = 0; i < attachmentCount; i++)
+	{
+		attachments[i]->clear(pClearValues[i], renderArea);
+	}
 }
 
 size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo* pCreateInfo)
 {
-	return 0;
+	return pCreateInfo->attachmentCount * sizeof(void*);
 }
 
 } // namespace vk
\ No newline at end of file
diff --git a/src/Vulkan/VkFramebuffer.hpp b/src/Vulkan/VkFramebuffer.hpp
index 6e4fc93..9049c17 100644
--- a/src/Vulkan/VkFramebuffer.hpp
+++ b/src/Vulkan/VkFramebuffer.hpp
@@ -20,6 +20,8 @@
 namespace vk
 {
 
+class ImageView;
+
 class Framebuffer : public Object<Framebuffer, VkFramebuffer>
 {
 public:
@@ -27,9 +29,13 @@
 	~Framebuffer() = delete;
 	void destroy(const VkAllocationCallbacks* pAllocator);
 
+	void clear(uint32_t clearValueCount, const VkClearValue* pClearValues, const VkRect2D& renderArea);
+
 	static size_t ComputeRequiredAllocationSize(const VkFramebufferCreateInfo* pCreateInfo);
 
 private:
+	uint32_t    attachmentCount = 0;
+	ImageView** attachments = nullptr;
 };
 
 static inline Framebuffer* Cast(VkFramebuffer object)
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 04f87f4..574b9aa 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -221,4 +221,18 @@
 	return extent.depth * slicePitchBytes();
 }
 
+void Image::clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange)
+{
+	if((subresourceRange.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
+	   (subresourceRange.baseMipLevel != 0) ||
+	   (subresourceRange.levelCount != 1) ||
+	   (subresourceRange.baseArrayLayer != 0) ||
+	   (subresourceRange.layerCount != 1))
+	{
+		UNIMPLEMENTED();
+	}
+
+	UNIMPLEMENTED();
+}
+
 } // namespace vk
\ No newline at end of file
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index 6fea3c5..82c725b 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -41,6 +41,11 @@
 	void copyTo(VkBuffer dstBuffer, const VkBufferImageCopy& pRegion);
 	void copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& pRegion);
 
+	void clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange);
+
+	VkImageType              getImageType() const { return imageType; }
+	VkFormat                 getFormat() const { return format; }
+
 private:
 	void* getTexelPointer(const VkOffset3D& offset) const;
 	VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D& offset) const;
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
new file mode 100644
index 0000000..746def5
--- /dev/null
+++ b/src/Vulkan/VkImageView.cpp
@@ -0,0 +1,55 @@
+// 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.
+
+#include "VkImageView.hpp"
+#include "VkImage.hpp"
+
+namespace vk
+{
+
+ImageView::ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem) :
+	image(pCreateInfo->image), viewType(pCreateInfo->viewType), format(pCreateInfo->format),
+	components(pCreateInfo->components), subresourceRange(pCreateInfo->subresourceRange)
+{
+}
+
+size_t ImageView::ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo)
+{
+	return 0;
+}
+
+void ImageView::destroy(const VkAllocationCallbacks* pAllocator)
+{
+}
+
+void ImageView::clear(const VkClearValue& clearValue, const VkRect2D& renderArea)
+{
+	// Note: clearing ignores swizzling, so components is ignored.
+
+	auto imageObject = Cast(image);
+
+	if(imageObject->getImageType() != viewType)
+	{
+		UNIMPLEMENTED();
+	}
+
+	if(imageObject->getFormat() != format)
+	{
+		UNIMPLEMENTED();
+	}
+
+	imageObject->clear(clearValue, renderArea, subresourceRange);
+}
+
+}
\ No newline at end of file
diff --git a/src/Vulkan/VkImageView.hpp b/src/Vulkan/VkImageView.hpp
new file mode 100644
index 0000000..06da799
--- /dev/null
+++ b/src/Vulkan/VkImageView.hpp
@@ -0,0 +1,51 @@
+// 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_IMAGE_VIEW_HPP_
+#define VK_IMAGE_VIEW_HPP_
+
+#include "VkDebug.hpp"
+#include "VkObject.hpp"
+#include "VkImage.hpp"
+
+namespace vk
+{
+
+class ImageView : public Object<ImageView, VkImageView>
+{
+public:
+	ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem);
+	~ImageView() = delete;
+	void destroy(const VkAllocationCallbacks* pAllocator);
+
+	static size_t ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo);
+
+	void clear(const VkClearValue& clearValues, const VkRect2D& renderArea);
+
+private:
+	VkImage                    image = VK_NULL_HANDLE;
+	VkImageViewType            viewType = VK_IMAGE_VIEW_TYPE_2D;
+	VkFormat                   format = VK_FORMAT_UNDEFINED;
+	VkComponentMapping         components = {};
+	VkImageSubresourceRange    subresourceRange = {};
+};
+
+static inline ImageView* Cast(VkImageView object)
+{
+	return reinterpret_cast<ImageView*>(object);
+}
+
+} // namespace vk
+
+#endif // VK_IMAGE_VIEW_HPP_
\ No newline at end of file
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 768f728..5853bf6 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -26,6 +26,7 @@
 #include "VkFramebuffer.hpp"
 #include "VkGetProcAddress.h"
 #include "VkImage.hpp"
+#include "VkImageView.hpp"
 #include "VkInstance.hpp"
 #include "VkPhysicalDevice.hpp"
 #include "VkPipeline.hpp"
@@ -808,21 +809,26 @@
 	TRACE("(VkDevice device = 0x%X, const VkImageViewCreateInfo* pCreateInfo = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X, VkImageView* pView = 0x%X)",
 		    device, pCreateInfo, pAllocator, pView);
 
-	UNIMPLEMENTED();
+	if(pCreateInfo->pNext || pCreateInfo->flags)
+	{
+		UNIMPLEMENTED();
+	}
 
-	return VK_SUCCESS;
+	return vk::ImageView::Create(pAllocator, pCreateInfo, pView);
 }
 
 VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator)
 {
-	TRACE("()");
-	UNIMPLEMENTED();
+	TRACE("(VkDevice device = 0x%X, VkImageView imageView = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X)",
+	      device, imageView, pAllocator);
+
+	vk::destroy(imageView, pAllocator);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule)
 {
 	TRACE("(VkDevice device = 0x%X, const VkShaderModuleCreateInfo* pCreateInfo = 0x%X, const VkAllocationCallbacks* pAllocator = 0x%X, VkShaderModule* pShaderModule = 0x%X)",
-	      device, pCreateInfo, pAllocator, pShaderModule);
+		    device, pCreateInfo, pAllocator, pShaderModule);
 
 	if(pCreateInfo->pNext || pCreateInfo->flags)
 	{
diff --git a/src/Vulkan/vulkan.vcxproj b/src/Vulkan/vulkan.vcxproj
index 6d06892..410fadf 100644
--- a/src/Vulkan/vulkan.vcxproj
+++ b/src/Vulkan/vulkan.vcxproj
@@ -109,6 +109,7 @@
     <ClCompile Include="VkFramebuffer.cpp" />

     <ClCompile Include="VkGetProcAddress.cpp" />

     <ClCompile Include="VkImage.cpp" />

+    <ClCompile Include="VkImageView.cpp" />

     <ClCompile Include="VkInstance.cpp" />

     <ClCompile Include="VkMemory.cpp" />

     <ClCompile Include="VkPhysicalDevice.cpp" />

@@ -203,6 +204,7 @@
     <ClInclude Include="VkFramebuffer.hpp" />

     <ClInclude Include="VkGetProcAddress.h" />

     <ClInclude Include="VkImage.hpp" />

+    <ClInclude Include="VkImageView.hpp" />

     <ClInclude Include="VkInstance.hpp" />

     <ClInclude Include="VkMemory.h" />

     <ClInclude Include="VkObject.hpp" />

diff --git a/src/Vulkan/vulkan.vcxproj.filters b/src/Vulkan/vulkan.vcxproj.filters
index ec3551e..865fa0b 100644
--- a/src/Vulkan/vulkan.vcxproj.filters
+++ b/src/Vulkan/vulkan.vcxproj.filters
@@ -237,6 +237,9 @@
     <ClCompile Include="VkImage.cpp">

       <Filter>Source Files\Vulkan</Filter>

     </ClCompile>

+    <ClCompile Include="VkImageView.cpp">

+      <Filter>Source Files\Vulkan</Filter>

+    </ClCompile>

     <ClCompile Include="VkPromotedExtensions.cpp">

       <Filter>Source Files\Vulkan</Filter>

     </ClCompile>

@@ -293,6 +296,9 @@
     <ClInclude Include="VkImage.hpp">

       <Filter>Header Files\Vulkan</Filter>

     </ClInclude>

+    <ClInclude Include="VkImageView.hpp">

+      <Filter>Header Files\Vulkan</Filter>

+    </ClInclude>

     <ClInclude Include="VkInstance.hpp">

       <Filter>Header Files\Vulkan</Filter>

     </ClInclude>