You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: replay.go
    path of file: ./repos/gapid/gapis/api/vulkan
    
    the code of the file until where you have to start completion: // Copyright (C) 2017 Google 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.

package vulkan

import (
	"bytes"
	"context"
	"fmt"
	"strings"

	"github.com/google/gapid/core/image"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/device"
	"github.com/google/gapid/gapis/api"
	"github.com/google/gapid/gapis/api/transform"
	"github.com/google/gapid/gapis/capture"
	"github.com/google/gapid/gapis/config"
	"github.com/google/gapid/gapis/memory"
	"github.com/google/gapid/gapis/replay"
	"github.com/google/gapid/gapis/resolve/dependencygraph2"
	"github.com/google/gapid/gapis/resolve/initialcmds"
	"github.com/google/gapid/gapis/service"
	"github.com/google/gapid/gapis/service/path"
	"github.com/google/gapid/gapis/trace"
)

var (
	// Interface compliance tests
	_ = replay.QueryIssues(API{})
	_ = replay.QueryFramebufferAttachment(API{})
	_ = replay.Support(API{})
	_ = replay.QueryTimestamps(API{})
	_ = replay.Profiler(API{})
)

// GetReplayPriority returns a uint32 representing the preference for
// replaying this trace on the given device.
// A lower number represents a higher priority, and Zero represents
// an inability for the trace to be replayed on the given device.
func (a API) GetReplayPriority(ctx context.Context, i *device.Instance, h *capture.Header) uint32 {
	devConf := i.GetConfiguration()
	devAbis := devConf.GetABIs()
	devVkDriver := devConf.GetDrivers().GetVulkan()
	traceVkDriver := h.GetDevice().GetConfiguration().GetDrivers().GetVulkan()

	if traceVkDriver == nil {
		log.E(ctx, "Vulkan trace does not contain VulkanDriver info.")
		return 0
	}

	// The device does not support Vulkan
	if devVkDriver == nil {
		return 0
	}

	for _, abi := range devAbis {
		// Memory layout must match.
		if !abi.GetMemoryLayout().SameAs(h.GetABI().GetMemoryLayout()) {
			continue
		}
		// If there is no physical devices, the trace must not contain
		// vkCreateInstance, any ABI compatible Vulkan device should be able to
		// replay.
		if len(traceVkDriver.GetPhysicalDevices()) == 0 {
			return 1
		}
		// Requires same vendor, device and version of API.
		for _, devPhyInfo := range devVkDriver.GetPhysicalDevices() {
			for _, tracePhyInfo := range traceVkDriver.GetPhysicalDevices() {
				// TODO: More sophisticated rules
				if devPhyInfo.GetVendorId() != tracePhyInfo.GetVendorId() {
					continue
				}
				if devPhyInfo.GetDeviceId() != tracePhyInfo.GetDeviceId() {
					continue
				}
				// Ignore the API patch level (bottom 12 bits) when comparing the API version.
				if (devPhyInfo.GetApiVersion() & ^uint32(0xfff)) != (tracePhyInfo.GetApiVersion() & ^uint32(0xfff)) {
					continue
				}
				return 1
			}
		}
	}
	return 0
}

// makeAttachementReadable is a transformation marking all color/depth/stencil
// attachment images created via vkCreateImage commands as readable (by patching
// the transfer src bit).
type makeAttachementReadable struct {
	imagesOnly bool
}

// drawConfig is a replay.Config used by colorBufferRequest and
// depthBufferRequests.
type drawConfig struct {
	startScope                api.CmdID
	endScope                  api.CmdID
	subindices                string // drawConfig needs to be comparable, so we cannot use a slice
	drawMode                  service.DrawMode
	disableReplayOptimization bool
}

type imgRes struct {
	img *image.Data // The image data.
	err error       // The error that occurred generating the image.
}

// framebufferRequest requests a postback of a framebuffer's attachment.
type framebufferRequest struct {
	after            []uint64
	width, height    uint32
	attachment       api.FramebufferAttachment
	framebufferIndex uint32
	out              chan imgRes
	wireframeOverlay bool
	displayToSurface bool
}

// color/depth/stencil attachment bit.
func patchImageUsage(usage VkImageUsageFlags) (VkImageUsageFlags, bool) {
	hasBit := func(flag VkImageUsageFlags, bit VkImageUsageFlagBits) bool {
		return (uint32(flag) & uint32(bit)) == uint32(bit)
	}

	if hasBit(usage, VkImageUsageFlagBits_VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) ||
		hasBit(usage, VkImageUsageFlagBits_VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
		return VkImageUsageFlags(uint32(usage) | uint32(VkImageUsageFlagBits_VK_IMAGE_USAGE_TRANSFER_SRC_BIT)), true
	}
	return usage, false
}

// Add VK_BUFFER_USAGE_TRANSFER_SRC_BIT to the buffer usage bit.
// TODO(renfeng) using shader to do the copy instead of change the usage bit.
func patchBufferusage(usage VkBufferUsageFlags) (VkBufferUsageFlags, bool) {
	hasBit := func(flag VkBufferUsageFlags, bit VkBufferUsageFlagBits) bool {
		return (uint32(flag) & uint32(bit)) == uint32(bit)
	}

	if hasBit(usage, VkBufferUsageFlagBits_VK_BUFFER_USAGE_TRANSFER_SRC_BIT) {
		return usage, false
	}

	return VkBufferUsageFlags(uint32(usage) | uint32(VkBufferUsageF
    
func (t *dropInvalidDestroy) Transform(ctx context.Context, id api.CmdID, cmd api.Cmd, out transform.Writer) error {
	s := out.State()
	l := s.MemoryLayout
	cb := CommandBuilder{Thread: cmd.Thread(), Arena: s.Arena}
	warnDropCmd := func(handles ...interface{}) {
		log.W(ctx, "[%v] Dropping [%d]:%v because the creation of %v was not recorded", t.tag, id, cmd, handles)
	}
	warnModCmd := func(handles ...interface{}) {
		log.W(ctx, "[%v] Modifing [%d]:%v to remove the reference to %v because the creation of them were not recorded", t.tag, id, cmd, handles)
	}
	switch cmd := cmd.(type) {
	case *VkDestroyInstance:
		if !GetState(s).Instances().Contains(cmd.Instance()) {
			warnDropCmd(cmd.Instance())
			return nil
		}
	case *VkDestroyDevice:
		if !GetState(s).Devices().Contains(cmd.Device()) {
			warnDropCmd(cmd.Device())
			return nil
		}
	case *VkFreeCommandBuffers:
		cmdBufCount := cmd.CommandBufferCount()
		if cmdBufCount > 0 {
			cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool())
			cmdBufs := cmd.PCommandBuffers().Slice(0, uint64(cmdBufCount), l).MustRead(ctx, cmd, s, nil)
			newCmdBufs := []VkCommandBuffer{}
			dropped := []VkCommandBuffer{}
			for _, b := range cmdBufs {
				if GetState(s).CommandBuffers().Contains(b) {
					newCmdBufs = append(newCmdBufs, b)
				} else {
					dropped = append(dropped, b)
				}
			}
			if len(newCmdBufs) == 0 {
				// no need to have this command
				warnDropCmd(cmdBufs)
				return nil
			}
			if len(newCmdBufs) != len(cmdBufs) {
				// need to modify the command to drop the command buffers not
				// in the state out of the command
				warnModCmd(dropped)
				newCmdBufsData := s.AllocDataOrPanic(ctx, newCmdBufs)
				defer newCmdBufsData.Free()
				newCmd := cb.VkFreeCommandBuffers(cmd.Device(), cmd.CommandPool(), uint32(len(newCmdBufs)), newCmdBufsData.Ptr()).AddRead(newCmdBufsData.Data())
				return out.MutateAndWrite(ctx, id, newCmd)
			}
			// No need to modify the command, just mutate and write the command
			// like others.
		}
	case *VkFreeMemory:
		if !GetState(s).DeviceMemories().Contains(cmd.Memory()) {
			warnDropCmd(cmd.Memory())
			return nil
		}
	case *VkDestroyBuffer:
		if !GetState(s).Buffers().Contains(cmd.Buffer()) {
			warnDropCmd(cmd.Buffer())
			return nil
		}
	case *VkDestroyBufferView:
		if !GetState(s).BufferViews().Contains(cmd.BufferView()) {
			warnDropCmd(cmd.BufferView())
			return nil
		}
	case *VkDestroyImage:
		if !GetState(s).Images().Contains(cmd.Image()) {
			warnDropCmd(cmd.Image())
			return nil
		}
	case *VkDestroyImageView:
		if !GetState(s).ImageViews().Contains(cmd.ImageView()) {
			warnDropCmd(cmd.ImageView())
			return nil
		}
	case *VkDestroyShaderModule:
		if !GetState(s).ShaderModules().Contains(cmd.ShaderModule()) {
			warnDropCmd(cmd.ShaderModule())
			return nil
		}
	case *VkDestroyPipeline:
		if !GetState(s).GraphicsPipelines().Contains(cmd.Pipeline()) &&
			!GetState(s).ComputePipelines().Contains(cmd.Pipeline()) {
			warnDropCmd(cmd.Pipeline())
			return nil
		}
	case *VkDestroyPipelineLayout:
		if !GetState(s).PipelineLayouts().Contains(cmd.PipelineLayout()) {
			warnDropCmd(cmd.PipelineLayout())
			return nil
		}
	case *VkDestroyPipelineCache:
		if !GetState(s).PipelineCaches().Contains(cmd.PipelineCache()) {
			warnDropCmd(cmd.PipelineCache())
			return nil
		}
	case *VkDestroySampler:
		if !GetState(s).Samplers().Contains(cmd.Sampler()) {
			warnDropCmd(cmd.Sampler())
			return nil
		}
	case *VkFreeDescriptorSets:
		descSetCount := cmd.DescriptorSetCount()
		if descSetCount > 0 {
			cmd.Extras().Observations().ApplyWrites(out.State().Memory.ApplicationPool())
			descSets := cmd.PDescriptorSets().Slice(0, uint64(descSetCount), l).MustRead(ctx, cmd, s, nil)
			newDescSets := []VkDescriptorSet{}
			dropped := []VkDescriptorSet{}
			for _, ds := range descSets {
				if GetState(s).DescriptorSets().Contains(ds) {
					newDescSets = append(newDescSets, ds)
				} else {
					dropped = append(dropped, ds)
				}
			}
			if len(newDescSets) == 0 {
				// no need to have this command
				warnDropCmd(descSets)
				return nil
			}
			if len(newDescSets) != len(descSets) {
				// need to modify the command to drop the command buffers not
				// in the state out of the command
				warnModCmd(dropped)
				newDescSetsData := s.AllocDataOrPanic(ctx, newDescSets)
				defer newDescSetsData.Free()
				newCmd := cb.VkFreeDescriptorSets(
					cmd.Device(), cmd.DescriptorPool(), uint32(len(newDescSets)),
					newDescSetsData.Ptr(), VkResult_VK_SUCCESS).AddRead(newDescSetsData.Data())
				return out.MutateAndWrite(ctx, id, newCmd)
			}
			// No need to modify the command, just mutate and write the command
			// like others.
		}
	case *VkDestroyDescriptorSetLayout:
		if !GetState(s).DescriptorSetLayouts().Contains(cmd.DescriptorSetLayout()) {
			warnDropCmd(cmd.DescriptorSetLayout())
			return nil
		}
	case *VkDestroyDescriptorPool:
		if !GetState(s).DescriptorPools().Contains(cmd.DescriptorPool()) {
			warnDropCmd(cmd.DescriptorPool())
			return nil
		}
	case *VkDestroyFence:
		if !GetState(s).Fences().Contains(cmd.Fence()) {
			warnDropCmd(cmd.Fence())
			return nil
		}
	case *VkDestroySemaphore:
		if !GetState(s).Semaphores().Contains(cmd.Semaphore()) {
			warnDropCmd(cmd.Semaphore())
			return nil
		}
	case *VkDestroyEvent:
		if !GetState(s).Events().Contains(cmd.Event()) {
			warnDropCmd(cmd.Event())
			return nil
		}
	case *VkDestroyQueryPool:
		if !GetState(s).QueryPools().Contains(cmd.QueryPool()) {
			warnDropCmd(cmd.QueryPool())
			return nil
		}
	case *VkDestroyFramebuffer:
		if !GetState(s).Framebuffers().Contains(cmd.Framebuffer()) {
			warnDropCmd(cmd.Framebuffer())
			return nil
		}
	case *VkDestroyRenderPass:
		if !GetState(s).RenderPasses().Contains(cmd.RenderPass()) {
			warnDropCmd(cmd.RenderPass())
			return nil
		}
	case *VkDestroyCommandPool:
		if !GetState(s).CommandPools().Contains(cmd.CommandPool()) {
			warnDropCmd(cmd.CommandPool())
			return nil
		}
	case *VkDestroySurfaceKHR:
		if !GetState(s).Surfaces().Contains(cmd.Surface()) {
			warnDropCmd(cmd.Surface())
			return nil
		}
	case *VkDestroySwapchainKHR:
		if !GetState(s).Swapchains().Contains(cmd.Swapchain()) {
			warnDropCmd(cmd.Swapchain())
			return nil
		}
	case *VkDestroyDebugReportCallbackEXT:
		if !GetState(s).DebugReportCallbacks().Contains(cmd.Callback()) {
			warnDropCmd(cmd.Callback())
			return nil
		}
	}
	return out.MutateAndWrite(ctx, id, cmd)
}