Replace uses of sw::Surface with vk::ImageView in the Renderer

sw::Surface contains a locking mechanism which is no longer required
in Vulkan. The app is now responsible for making sure the lifetime of
the objects is long enough for the driver to be able to use them in
any operation where they are required.

A few shortcuts were taken here:
- ImageView::getSampleCount() currently always returns the largest
  available sample count.
- ImageView::subresourceRange.levelCount is not taken into account
- Context::getMultiSampleCount() still uses attachment 0 to get
  the samples count, which may be incorrect.

Bug b/118619338

Change-Id: I8cd49926a1537c0f2bc20e6516f12d7de67d6c65
Reviewed-on: https://swiftshader-review.googlesource.com/c/25588
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index f18b4a8..d4ed3dc 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -18,6 +18,7 @@
 #include "Surface.hpp"
 #include "System/Memory.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "Vulkan/VkImageView.hpp"
 #include "Pipeline/SpirvShader.hpp"
 
 #include <string.h>
@@ -714,14 +715,14 @@
 
 	int Context::getMultiSampleCount() const
 	{
-		return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
+		return renderTarget[0] ? renderTarget[0]->getSampleCount() : 1;
 	}
 
 	VkFormat Context::renderTargetInternalFormat(int index)
 	{
 		if(renderTarget[index])
 		{
-			return renderTarget[index]->getInternalFormat();
+			return renderTarget[index]->getFormat();
 		}
 		else
 		{
@@ -736,7 +737,7 @@
 
 	int Context::colorWriteActive(int index)
 	{
-		if(!renderTarget[index] || renderTarget[index]->getInternalFormat() == VK_FORMAT_UNDEFINED)
+		if(!renderTarget[index] || renderTarget[index]->getFormat() == VK_FORMAT_UNDEFINED)
 		{
 			return 0;
 		}
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index e8c7754..daa2420 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -21,10 +21,14 @@
 #include "Vertex.hpp"
 #include "System/Types.hpp"
 
+namespace vk
+{
+	class ImageView;
+};
+
 namespace sw
 {
 	class Sampler;
-	class Surface;
 	class PixelShader;
 	class VertexShader;
 	class SpirvShader;
@@ -191,15 +195,15 @@
 		int colorWriteActive(int index);
 		bool colorUsed();
 
-		Resource *texture[TOTAL_IMAGE_UNITS];
+		vk::ImageView *texture[TOTAL_IMAGE_UNITS];
 		Stream input[MAX_VERTEX_INPUTS];
-		Resource *indexBuffer;
+		uint8_t *indexBuffer;
 
-		Surface *renderTarget[RENDERTARGETS];
+		vk::ImageView *renderTarget[RENDERTARGETS];
 		unsigned int renderTargetLayer[RENDERTARGETS];
-		Surface *depthBuffer;
+		vk::ImageView *depthBuffer;
 		unsigned int depthBufferLayer;
-		Surface *stencilBuffer;
+		vk::ImageView *stencilBuffer;
 		unsigned int stencilBufferLayer;
 
 		// Shaders
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index 30a4125..0d43b81 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -19,6 +19,7 @@
 #include "Pipeline/PixelProgram.hpp"
 #include "Pipeline/Constants.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "Vulkan/VkImageView.hpp"
 
 #include <string.h>
 
@@ -70,24 +71,24 @@
 		routineCache = nullptr;
 	}
 
-	void PixelProcessor::setRenderTarget(int index, Surface *renderTarget, unsigned int layer)
+	void PixelProcessor::setRenderTarget(int index, vk::ImageView* renderTarget, unsigned int layer)
 	{
 		context->renderTarget[index] = renderTarget;
 		context->renderTargetLayer[index] = layer;
 	}
 
-	Surface *PixelProcessor::getRenderTarget(int index)
+	vk::ImageView* PixelProcessor::getRenderTarget(int index)
 	{
 		return context->renderTarget[index];
 	}
 
-	void PixelProcessor::setDepthBuffer(Surface *depthBuffer, unsigned int layer)
+	void PixelProcessor::setDepthBuffer(vk::ImageView *depthBuffer, unsigned int layer)
 	{
 		context->depthBuffer = depthBuffer;
 		context->depthBufferLayer = layer;
 	}
 
-	void PixelProcessor::setStencilBuffer(Surface *stencilBuffer, unsigned int layer)
+	void PixelProcessor::setStencilBuffer(vk::ImageView *stencilBuffer, unsigned int layer)
 	{
 		context->stencilBuffer = stencilBuffer;
 		context->stencilBufferLayer = layer;
@@ -596,7 +597,7 @@
 		{
 			state.depthTestActive = true;
 			state.depthCompareMode = context->depthCompareMode;
-			state.quadLayoutDepthBuffer = Surface::hasQuadLayout(context->depthBuffer->getInternalFormat());
+			state.quadLayoutDepthBuffer = Surface::hasQuadLayout(context->depthBuffer->getFormat());
 		}
 
 		state.occlusionEnabled = context->occlusionEnabled;
@@ -623,7 +624,7 @@
 			state.targetFormat[i] = context->renderTargetInternalFormat(i);
 		}
 
-		state.writeSRGB	= context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getExternalFormat());
+		state.writeSRGB	= context->writeSRGB && context->renderTarget[0] && Surface::isSRGBwritable(context->renderTarget[0]->getFormat());
 		state.multiSample = context->getMultiSampleCount();
 		state.multiSampleMask = context->multiSampleMask;
 
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index 7b37266..9a0d20f 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -145,10 +145,10 @@
 
 		virtual ~PixelProcessor();
 
-		void setRenderTarget(int index, Surface *renderTarget, unsigned int layer = 0);
-		Surface *getRenderTarget(int index);
-		void setDepthBuffer(Surface *depthBuffer, unsigned int layer = 0);
-		void setStencilBuffer(Surface *stencilBuffer, unsigned int layer = 0);
+		void setRenderTarget(int index, vk::ImageView *renderTarget, unsigned int layer = 0);
+		vk::ImageView *getRenderTarget(int index);
+		void setDepthBuffer(vk::ImageView *depthBuffer, unsigned int layer = 0);
+		void setStencilBuffer(vk::ImageView *stencilBuffer, unsigned int layer = 0);
 
 		void setTexCoordIndex(unsigned int stage, int texCoordIndex);
 		void setConstantColor(unsigned int stage, const Color<float> &constantColor);
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 13e62a8..405fe4b 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -30,6 +30,7 @@
 #include "System/Math.hpp"
 #include "System/Timer.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "Vulkan/VkImageView.hpp"
 #include "Pipeline/SpirvShader.hpp"
 #include "Vertex.hpp"
 
@@ -325,7 +326,7 @@
 
 		if(context->indexBuffer)
 		{
-			data->indices = (unsigned char*)context->indexBuffer->lock(PUBLIC, PRIVATE) + indexOffset;
+			data->indices = &context->indexBuffer[indexOffset];
 		}
 
 		draw->indexBuffer = context->indexBuffer;
@@ -340,8 +341,6 @@
 			if(pixelState.sampler[sampler].textureType != TEXTURE_NULL)
 			{
 				draw->texture[sampler] = context->texture[sampler];
-				draw->texture[sampler]->lock(PUBLIC, isReadWriteTexture(sampler) ? MANAGED : PRIVATE);   // If the texure is both read and written, use the same read/write lock as render targets
-
 				data->mipmap[sampler] = context->sampler[sampler].getTextureData();
 			}
 		}
@@ -351,8 +350,6 @@
 			if(vertexState.sampler[sampler].textureType != TEXTURE_NULL)
 			{
 				draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
-				draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
-
 				data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
 			}
 		}
@@ -457,10 +454,10 @@
 
 				if(draw->renderTarget[index])
 				{
-					unsigned int layer = context->renderTargetLayer[index];
-					data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
-					data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
-					data->colorSliceB[index] = context->renderTarget[index]->getInternalSliceB();
+					VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->renderTargetLayer[index]) };
+					data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->getOffsetPointer(offset);
+					data->colorPitchB[index] = context->renderTarget[index]->rowPitchBytes();
+					data->colorSliceB[index] = context->renderTarget[index]->slicePitchBytes();
 				}
 			}
 
@@ -469,18 +466,18 @@
 
 			if(draw->depthBuffer)
 			{
-				unsigned int layer = context->depthBufferLayer;
-				data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
-				data->depthPitchB = context->depthBuffer->getInternalPitchB();
-				data->depthSliceB = context->depthBuffer->getInternalSliceB();
+				VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->depthBufferLayer) };
+				data->depthBuffer = (float*)context->depthBuffer->getOffsetPointer(offset);
+				data->depthPitchB = context->depthBuffer->rowPitchBytes();
+				data->depthSliceB = context->depthBuffer->slicePitchBytes();
 			}
 
 			if(draw->stencilBuffer)
 			{
-				unsigned int layer = context->stencilBufferLayer;
-				data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, layer, MANAGED);
-				data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
-				data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
+				VkOffset3D offset = { 0, 0, static_cast<int32_t>(context->stencilBufferLayer) };
+				data->stencilBuffer = (unsigned char*)context->stencilBuffer->getOffsetPointer(offset);
+				data->stencilPitchB = context->stencilBuffer->rowPitchBytes();
+				data->stencilSliceB = context->stencilBuffer->slicePitchBytes();
 			}
 		}
 
@@ -842,32 +839,6 @@
 					draw.queries = 0;
 				}
 
-				for(int i = 0; i < RENDERTARGETS; i++)
-				{
-					if(draw.renderTarget[i])
-					{
-						draw.renderTarget[i]->unlockInternal();
-					}
-				}
-
-				if(draw.depthBuffer)
-				{
-					draw.depthBuffer->unlockInternal();
-				}
-
-				if(draw.stencilBuffer)
-				{
-					draw.stencilBuffer->unlockStencil();
-				}
-
-				for(int i = 0; i < TOTAL_IMAGE_UNITS; i++)
-				{
-					if(draw.texture[i])
-					{
-						draw.texture[i]->unlock();
-					}
-				}
-
 				for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
 				{
 					if(draw.vertexStream[i])
@@ -876,11 +847,6 @@
 					}
 				}
 
-				if(draw.indexBuffer)
-				{
-					draw.indexBuffer->unlock();
-				}
-
 				draw.vertexRoutine->unbind();
 				draw.setupRoutine->unbind();
 				draw.pixelRoutine->unbind();
@@ -1614,7 +1580,7 @@
 		}
 	}
 
-	void Renderer::setIndexBuffer(Resource *indexBuffer)
+	void Renderer::setIndexBuffer(uint8_t *indexBuffer)
 	{
 		context->indexBuffer = indexBuffer;
 	}
@@ -1633,13 +1599,13 @@
 	{
 		for(int index = 0; index < RENDERTARGETS; index++)
 		{
-			if(context->renderTarget[index] && context->texture[sampler] == context->renderTarget[index]->getResource())
+			if(context->renderTarget[index] && context->texture[sampler] == context->renderTarget[index])
 			{
 				return true;
 			}
 		}
 
-		if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
+		if(context->depthBuffer && context->texture[sampler] == context->depthBuffer)
 		{
 			return true;
 		}
@@ -1647,7 +1613,7 @@
 		return false;
 	}
 
-	void Renderer::setTextureResource(unsigned int sampler, Resource *resource)
+	void Renderer::setTextureResource(unsigned int sampler, vk::ImageView *resource)
 	{
 		ASSERT(sampler < TOTAL_IMAGE_UNITS);
 
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 4724086..e31e6de 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -257,12 +257,12 @@
 		void blit3D(Surface *source, Surface *dest);
 
 		void setContext(const sw::Context& context);
-		void setIndexBuffer(Resource *indexBuffer);
+		void setIndexBuffer(uint8_t *indexBuffer);
 
 		void setMultiSampleMask(unsigned int mask);
 		void setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing);
 
-		void setTextureResource(unsigned int sampler, Resource *resource);
+		void setTextureResource(unsigned int sampler, vk::ImageView *resource);
 		void setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type);
 
 		void setTextureFilter(SamplerType type, int sampler, FilterType textureFilter);
@@ -427,11 +427,11 @@
 		SetupProcessor::State setupState;
 
 		Resource *vertexStream[MAX_VERTEX_INPUTS];
-		Resource *indexBuffer;
-		Surface *renderTarget[RENDERTARGETS];
-		Surface *depthBuffer;
-		Surface *stencilBuffer;
-		Resource *texture[TOTAL_IMAGE_UNITS];
+		uint8_t *indexBuffer;
+		vk::ImageView *renderTarget[RENDERTARGETS];
+		vk::ImageView *depthBuffer;
+		vk::ImageView *stencilBuffer;
+		vk::ImageView *texture[TOTAL_IMAGE_UNITS];
 
 		std::list<Query*> *queries;
 
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index 5113021..50053be 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -176,7 +176,7 @@
 			if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
 			{
 				auto attachment = executionState.renderPassFramebuffer->getAttachment(attachmentReference.attachment);
-				executionState.renderer->setRenderTarget(i, attachment->asSurface(), 0);
+				executionState.renderer->setRenderTarget(i, attachment, 0);
 			}
 		}
 
@@ -190,19 +190,6 @@
 
 		// Wait for completion. We should be able to get rid of this eventually.
 		executionState.renderer->synchronize();
-
-		// Renderer has finished touching the color attachments; destroy the temporary Surface objects.
-		// We shouldn't need to do any of this at draw time.
-		for (auto i = 0u; i < executionState.renderPass->getCurrentSubpass().colorAttachmentCount; i++)
-		{
-			auto attachmentReference = executionState.renderPass->getCurrentSubpass().pColorAttachments[i];
-			if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
-			{
-				auto surface = executionState.renderer->getRenderTarget(i);
-				executionState.renderer->setRenderTarget(i, nullptr, 0);
-				delete surface;
-			}
-		}
 	}
 
 	uint32_t vertexCount;
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index 68ca016..594091a 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -48,25 +48,26 @@
 	void clear(const VkClearValue& clearValue, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange);
 	void clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange);
 	void clear(const VkClearDepthStencilValue& color, const VkImageSubresourceRange& subresourceRange);
-	sw::Surface* asSurface(const VkImageAspectFlags& flags, uint32_t mipLevel, uint32_t layer) const;
 
 	VkImageType              getImageType() const { return imageType; }
 	VkFormat                 getFormat() const { return format; }
 	uint32_t                 getArrayLayers() const { return arrayLayers; }
+	VkSampleCountFlagBits    getSampleCountFlagBits() const { return samples; }
+	int                      rowPitchBytes(const VkImageAspectFlags& flags, uint32_t mipLevel) const;
+	int                      slicePitchBytes(const VkImageAspectFlags& flags, uint32_t mipLevel) const;
+	void*                    getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const;
 	bool                     isCube() const;
 
 private:
+	sw::Surface* asSurface(const VkImageAspectFlags& flags, uint32_t mipLevel, uint32_t layer) const;
 	void copy(VkBuffer buffer, const VkBufferImageCopy& region, bool bufferIsSource);
 	VkDeviceSize getStorageSize(const VkImageAspectFlags& flags) const;
 	VkDeviceSize getMipLevelSize(const VkImageAspectFlags& flags, uint32_t mipLevel) const;
 	VkDeviceSize getLayerSize(const VkImageAspectFlags& flags) const;
 	VkDeviceSize getMemoryOffset(const VkImageAspectFlags& flags, uint32_t mipLevel) const;
 	VkDeviceSize getMemoryOffset(const VkImageAspectFlags& flags, uint32_t mipLevel, uint32_t layer) const;
-	void* getTexelPointer(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const;
 	VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D& offset, const VkImageSubresourceLayers& subresource) const;
 	VkDeviceSize getMemoryOffset(const VkImageAspectFlags& flags) const;
-	int rowPitchBytes(const VkImageAspectFlags& flags, uint32_t mipLevel) const;
-	int slicePitchBytes(const VkImageAspectFlags& flags, uint32_t mipLevel) const;
 	int bytesPerTexel(const VkImageAspectFlags& flags) const;
 	VkExtent3D getMipLevelExtent(uint32_t mipLevel) const;
 	VkFormat getFormat(const VkImageAspectFlags& flags) const;
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index c0ac795..367c602 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -119,9 +119,22 @@
 	image->clear(clearValue, renderArea.rect, sr);
 }
 
-sw::Surface *ImageView::asSurface()
+void *ImageView::getPointer() const
 {
-	return image->asSurface(subresourceRange.aspectMask, subresourceRange.baseArrayLayer, subresourceRange.baseMipLevel);
+	VkOffset3D noOffset = { 0, 0, 0 };
+	return getOffsetPointer(noOffset);
+}
+
+void *ImageView::getOffsetPointer(const VkOffset3D& offset) const
+{
+	VkImageSubresourceLayers imageSubresourceLayers =
+	{
+		subresourceRange.aspectMask,
+		subresourceRange.baseMipLevel,
+		subresourceRange.baseArrayLayer,
+		subresourceRange.layerCount
+	};
+	return image->getTexelPointer(offset, imageSubresourceLayers);
 }
 
 }
\ No newline at end of file
diff --git a/src/Vulkan/VkImageView.hpp b/src/Vulkan/VkImageView.hpp
index 8eb3ee5..83fb289 100644
--- a/src/Vulkan/VkImageView.hpp
+++ b/src/Vulkan/VkImageView.hpp
@@ -34,7 +34,13 @@
 	void clear(const VkClearValue& clearValues, const VkImageAspectFlags aspectMask, const VkRect2D& renderArea);
 	void clear(const VkClearValue& clearValue, const VkImageAspectFlags aspectMask, const VkClearRect& renderArea);
 
-	sw::Surface *asSurface();
+	VkFormat getFormat() const { return format; }
+	int rowPitchBytes() const { return image->rowPitchBytes(subresourceRange.aspectMask, subresourceRange.baseMipLevel); }
+	int slicePitchBytes() const { return image->slicePitchBytes(subresourceRange.aspectMask, subresourceRange.baseMipLevel); }
+	int getSampleCount() const { return image->getSampleCountFlagBits(); }
+
+	void *getPointer() const;
+	void *getOffsetPointer(const VkOffset3D& offset) const;
 
 private:
 	bool                       imageTypesMatch(VkImageType imageType) const;