<commit_before>//===- SymbolTable.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "SymbolTable.h"

#include "Config.h"
#include "InputChunks.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
#include "llvm/ADT/SetVector.h"

#define DEBUG_TYPE "lld"

using namespace llvm;
using namespace llvm::wasm;
using namespace lld;
using namespace lld::wasm;

SymbolTable *lld::wasm::Symtab;

void SymbolTable::addFile(InputFile *File) {
  log("Processing: " + toString(File));
  File->parse();

  if (auto *F = dyn_cast<ObjFile>(File))
    ObjectFiles.push_back(F);
}

void SymbolTable::reportRemainingUndefines() {
  SetVector<Symbol *> Undefs;
  for (Symbol *Sym : SymVector) {
    if (Sym->isUndefined() && !Sym->isWeak() &&
        Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
      Undefs.insert(Sym);
    }
  }

  if (Undefs.empty())
    return;

  for (ObjFile *File : ObjectFiles)
    for (Symbol *Sym : File->getSymbols())
      if (Undefs.count(Sym))
        error(toString(File) + ": undefined symbol: " + toString(*Sym));

  for (Symbol *Sym : Undefs)
    if (!Sym->getFile())
      error("undefined symbol: " + toString(*Sym));
}

Symbol *SymbolTable::find(StringRef Name) {
  auto It = SymMap.find(CachedHashStringRef(Name));
  if (It == SymMap.end())
    return nullptr;
  return It->second;
}

std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
  Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
  if (Sym)
    return {Sym, false};
  Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
  SymVector.emplace_back(Sym);
  return {Sym, true};
}

// Check the type of new symbol matches that of the symbol is replacing.
// For functions this can also involve verifying that the signatures match.
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
                             bool NewIsFunction, const WasmSignature *NewSig) {
  if (Existing.isLazy())
    return;

  // First check the symbol types match (i.e. either both are function
  // symbols or both are data symbols).
  if (isa<FunctionSymbol>(Existing) != NewIsFunction) {
    error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
          (isa<FunctionSymbol>(Existing) ? "Function" : "Global") + " in " +
          toString(Existing.getFile()) + "\n>>> defined as " +
          (NewIsFunction ? "Function" : "Global") + " in " + F.getName());
    return;
  }

  // For function symbols, optionally check the function signature matches too.
  auto *ExistingFunc = dyn_cast<FunctionSymbol>(&Existing);
  if (!ExistingFunc || !Config->CheckSignatures)
    return;

  const WasmSignature *OldSig = ExistingFunc->getFunctionType();

  // Skip the signature check if the existing function has no signature (e.g.
  // if it is an undefined symbol generated by --undefined command line flag).
  if (OldSig == nullptr)
    return;

  DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n");
  assert(NewSig);

  if (*NewSig == *OldSig)
    return;

  error("function signature mismatch: " + ExistingFunc->getName() +
        "\n>>> defined as " + toString(*OldSig) + " in " +
        toString(ExistingFunc->getFile()) + "\n>>> defined as " +
        toString(*NewSig) + " in " + F.getName());
}

static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
                             bool IsFunction, const InputChunk *Chunk) {
  const WasmSignature *Sig = nullptr;
  if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
    Sig = &F->Signature;
  return checkSymbolTypes(Existing, F, IsFunction, Sig);
}

DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
                                                   const WasmSignature *Type,
                                                   uint32_t Flags) {
  DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  assert(WasInserted);
  return replaceSymbol<DefinedFunction>(S, Name, Flags, Type);
}

DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags) {
  DEBUG(dbgs() << "addSyntheticGlobal: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  assert(WasInserted);
  return replaceSymbol<DefinedGlobal>(S, Name, Flags);
}

struct NewSymbol {
  InputFile *File;
  uint32_t Flags;
  InputChunk *Chunk;
  bool IsFunction;
};

static bool shouldReplace(const Symbol &Existing, const NewSymbol &New) {
  bool Replace = false;
  bool CheckTypes = false;

  if (Existing.isLazy()) {
    // Existing symbol is lazy. Replace it without checking types since
    // lazy symbols don't have any type information.
    DEBUG(dbgs() << "replacing existing lazy symbol: " << Existing.getName()
                 << "\n");
    Replace = true;
  } else if (!Existing.isDefined()) {
    // Existing symbol is undefined: replace it, while check types.
    DEBUG(dbgs() << "resolving existing undefined symbol: "
                 << Existing.getName() << "\n");
    Replace = true;
    CheckTypes = true;
  } else if ((New.Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
    // the new symbol is weak we can ignore it
    DEBUG(dbgs() << "existing symbol takes precedence\n");
    CheckTypes = true;
  } else if (Existing.isWeak()) {
    // the existing symbol is, so we replace it
    DEBUG(dbgs() << "replacing existing weak symbol\n");
    Replace = true;
    CheckTypes = true;
  } else {
    // neither symbol is week. They conflict.
    error("duplicate symbol: " + toString(Existing) + "\n>>> defined in " +
          toString(Existing.getFile()) + "\n>>> defined in " +
          toString(New.File));
  }

  if (CheckTypes)
    checkSymbolTypes(Existing, *New.File, New.IsFunction, New.Chunk);

  return Replace;
}

Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
                                        InputFile *F, InputFunction *Function) {
  DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  NewSymbol New{F, Flags, Function, true};
  if (WasInserted || shouldReplace(*S, New))
    replaceSymbol<DefinedFunction>(S, Name, Flags, F, Function);
  return S;
}

Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
                                      InputFile *F, InputSegment *Segment,
                                      uint32_t Address) {
  DEBUG(dbgs() << "addDefinedGlobal:" << Name << " addr:" << Address << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  NewSymbol New{F, Flags, Segment, false};
  if (WasInserted || shouldReplace(*S, New))
    replaceSymbol<DefinedGlobal>(S, Name, Flags, F, Segment, Address);
  return S;
}

Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
                                  uint32_t Flags, InputFile *F,
                                  const WasmSignature *Type) {
  DEBUG(dbgs() << "addUndefined: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  bool IsFunction = Kind == Symbol::UndefinedFunctionKind;
  if (WasInserted) {
    if (IsFunction)
      replaceSymbol<UndefinedFunction>(S, Name, Flags, F, Type);
    else
      replaceSymbol<UndefinedGlobal>(S, Name, Flags, F);
  } else if (auto *LazySym = dyn_cast<LazySymbol>(S)) {
    DEBUG(dbgs() << "resolved by existing lazy\n");
    auto *AF = cast<ArchiveFile>(LazySym->getFile());
    AF->addMember(&LazySym->getArchiveSymbol());
  } else if (S->isDefined()) {
    DEBUG(dbgs() << "resolved by existing\n");
    checkSymbolTypes(*S, *F, IsFunction, Type);
  }
  return S;
}

void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
  DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
  StringRef Name = Sym->getName();
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  if (WasInserted) {
    replaceSymbol<LazySymbol>(S, Name, F, *Sym);
  } else if (S->isUndefined()) {
    // There is an existing undefined symbol.  The can load from the
    // archive.
    DEBUG(dbgs() << "replacing existing undefined\n");
    F->addMember(Sym);
  }
}

bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
  DEBUG(dbgs() << "addComdat: " << Name << "\n");
  ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
  if (File) {
    DEBUG(dbgs() << "COMDAT already defined\n");
    return false;
  }
  File = F;
  return true;
}

ObjFile *SymbolTable::findComdat(StringRef Name) const {
  auto It = ComdatMap.find(CachedHashStringRef(Name));
  return It == ComdatMap.end() ? nullptr : It->second;
}
<commit_msg>feedback<commit_after>//===- SymbolTable.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "SymbolTable.h"

#include "Config.h"
#include "InputChunks.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
#include "llvm/ADT/SetVector.h"

#define DEBUG_TYPE "lld"

using namespace llvm;
using namespace llvm::wasm;
using namespace lld;
using namespace lld::wasm;

SymbolTable *lld::wasm::Symtab;

void SymbolTable::addFile(InputFile *File) {
  log("Processing: " + toString(File));
  File->parse();

  if (auto *F = dyn_cast<ObjFile>(File))
    ObjectFiles.push_back(F);
}

void SymbolTable::reportRemainingUndefines() {
  SetVector<Symbol *> Undefs;
  for (Symbol *Sym : SymVector) {
    if (Sym->isUndefined() && !Sym->isWeak() &&
        Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
      Undefs.insert(Sym);
    }
  }

  if (Undefs.empty())
    return;

  for (ObjFile *File : ObjectFiles)
    for (Symbol *Sym : File->getSymbols())
      if (Undefs.count(Sym))
        error(toString(File) + ": undefined symbol: " + toString(*Sym));

  for (Symbol *Sym : Undefs)
    if (!Sym->getFile())
      error("undefined symbol: " + toString(*Sym));
}

Symbol *SymbolTable::find(StringRef Name) {
  auto It = SymMap.find(CachedHashStringRef(Name));
  if (It == SymMap.end())
    return nullptr;
  return It->second;
}

std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
  Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
  if (Sym)
    return {Sym, false};
  Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
  SymVector.emplace_back(Sym);
  return {Sym, true};
}

// Check the type of new symbol matches that of the symbol is replacing.
// For functions this can also involve verifying that the signatures match.
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
                             bool NewIsFunction, const WasmSignature *NewSig) {
  if (Existing.isLazy())
    return;

  // First check the symbol types match (i.e. either both are function
  // symbols or both are data symbols).
  if (isa<FunctionSymbol>(Existing) != NewIsFunction) {
    error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
          (isa<FunctionSymbol>(Existing) ? "Function" : "Global") + " in " +
          toString(Existing.getFile()) + "\n>>> defined as " +
          (NewIsFunction ? "Function" : "Global") + " in " + F.getName());
    return;
  }

  // For function symbols, optionally check the function signature matches too.
  auto *ExistingFunc = dyn_cast<FunctionSymbol>(&Existing);
  if (!ExistingFunc || !Config->CheckSignatures)
    return;

  const WasmSignature *OldSig = ExistingFunc->getFunctionType();

  // Skip the signature check if the existing function has no signature (e.g.
  // if it is an undefined symbol generated by --undefined command line flag).
  if (OldSig == nullptr)
    return;

  DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n");
  assert(NewSig);

  if (*NewSig == *OldSig)
    return;

  error("function signature mismatch: " + ExistingFunc->getName() +
        "\n>>> defined as " + toString(*OldSig) + " in " +
        toString(ExistingFunc->getFile()) + "\n>>> defined as " +
        toString(*NewSig) + " in " + F.getName());
}

static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
                             bool IsFunction, const InputChunk *Chunk) {
  const WasmSignature *Sig = nullptr;
  if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
    Sig = &F->Signature;
  return checkSymbolTypes(Existing, F, IsFunction, Sig);
}

DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
                                                   const WasmSignature *Type,
                                                   uint32_t Flags) {
  DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  assert(WasInserted);
  return replaceSymbol<DefinedFunction>(S, Name, Flags, Type);
}

DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags) {
  DEBUG(dbgs() << "addSyntheticGlobal: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  assert(WasInserted);
  return replaceSymbol<DefinedGlobal>(S, Name, Flags);
}

static bool shouldReplace(const Symbol &Existing, InputFile *NewFile,
                          uint32_t NewFlags, InputChunk *NewChunk,
                          bool NewIsFunction) {
  bool Replace = false;
  bool CheckTypes = false;

  if (Existing.isLazy()) {
    // Existing symbol is lazy. Replace it without checking types since
    // lazy symbols don't have any type information.
    DEBUG(dbgs() << "replacing existing lazy symbol: " << Existing.getName()
                 << "\n");
    Replace = true;
  } else if (!Existing.isDefined()) {
    // Existing symbol is undefined: replace it, while check types.
    DEBUG(dbgs() << "resolving existing undefined symbol: "
                 << Existing.getName() << "\n");
    Replace = true;
    CheckTypes = true;
  } else if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
    // the new symbol is weak we can ignore it
    DEBUG(dbgs() << "existing symbol takes precedence\n");
    CheckTypes = true;
  } else if (Existing.isWeak()) {
    // the existing symbol is, so we replace it
    DEBUG(dbgs() << "replacing existing weak symbol\n");
    Replace = true;
    CheckTypes = true;
  } else {
    // neither symbol is week. They conflict.
    error("duplicate symbol: " + toString(Existing) + "\n>>> defined in " +
          toString(Existing.getFile()) + "\n>>> defined in " +
          toString(NewFile));
  }

  if (CheckTypes)
    checkSymbolTypes(Existing, *NewFile, NewIsFunction, NewChunk);

  return Replace;
}

Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
                                        InputFile *F, InputFunction *Function) {
  DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  if (WasInserted || shouldReplace(*S, F, Flags, Function, true))
    replaceSymbol<DefinedFunction>(S, Name, Flags, F, Function);
  return S;
}

Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
                                      InputFile *F, InputSegment *Segment,
                                      uint32_t Address) {
  DEBUG(dbgs() << "addDefinedGlobal:" << Name << " addr:" << Address << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  if (WasInserted || shouldReplace(*S, F, Flags, Segment, false))
    replaceSymbol<DefinedGlobal>(S, Name, Flags, F, Segment, Address);
  return S;
}

Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
                                  uint32_t Flags, InputFile *F,
                                  const WasmSignature *Type) {
  DEBUG(dbgs() << "addUndefined: " << Name << "\n");
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  bool IsFunction = Kind == Symbol::UndefinedFunctionKind;
  if (WasInserted) {
    if (IsFunction)
      replaceSymbol<UndefinedFunction>(S, Name, Flags, F, Type);
    else
      replaceSymbol<UndefinedGlobal>(S, Name, Flags, F);
  } else if (auto *LazySym = dyn_cast<LazySymbol>(S)) {
    DEBUG(dbgs() << "resolved by existing lazy\n");
    auto *AF = cast<ArchiveFile>(LazySym->getFile());
    AF->addMember(&LazySym->getArchiveSymbol());
  } else if (S->isDefined()) {
    DEBUG(dbgs() << "resolved by existing\n");
    checkSymbolTypes(*S, *F, IsFunction, Type);
  }
  return S;
}

void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
  DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
  StringRef Name = Sym->getName();
  Symbol *S;
  bool WasInserted;
  std::tie(S, WasInserted) = insert(Name);
  if (WasInserted) {
    replaceSymbol<LazySymbol>(S, Name, F, *Sym);
  } else if (S->isUndefined()) {
    // There is an existing undefined symbol.  The can load from the
    // archive.
    DEBUG(dbgs() << "replacing existing undefined\n");
    F->addMember(Sym);
  }
}

bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
  DEBUG(dbgs() << "addComdat: " << Name << "\n");
  ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
  if (File) {
    DEBUG(dbgs() << "COMDAT already defined\n");
    return false;
  }
  File = F;
  return true;
}

ObjFile *SymbolTable::findComdat(StringRef Name) const {
  auto It = ComdatMap.find(CachedHashStringRef(Name));
  return It == ComdatMap.end() ? nullptr : It->second;
}
<|endoftext|>


<commit_before>/*
* Class wrapping access to the swap chain
*
* A swap chain is a collection of framebuffers used for rendering
* The swap chain images can then presented to the windowing system
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#include <stdlib.h>
#include <string>
#include <fstream>
#include <assert.h>
#include <stdio.h>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#else
#endif

#include <vulkan/vulkan.h>
#include "vulkantools.h"

#ifdef __ANDROID__
#include "vulkanandroid.h"
#endif

// Macro to get a procedure address based on a vulkan instance
#define GET_INSTANCE_PROC_ADDR(inst, entrypoint)                        \
{                                                                       \
    fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
    if (fp##entrypoint == NULL)                                         \
	{																    \
        exit(1);                                                        \
    }                                                                   \
}

// Macro to get a procedure address based on a vulkan device
#define GET_DEVICE_PROC_ADDR(dev, entrypoint)                           \
{                                                                       \
    fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint);   \
    if (fp##entrypoint == NULL)                                         \
	{																    \
        exit(1);                                                        \
    }                                                                   \
}

typedef struct _SwapChainBuffers {
	VkImage image;
	VkImageView view;
} SwapChainBuffer;

class VulkanSwapChain
{
private:
	VkInstance instance;
	VkDevice device;
	VkPhysicalDevice physicalDevice;
	VkSurfaceKHR surface;
	// Function pointers
	PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR;
	PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
	PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR;
	PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR;
	PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
	PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
	PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
	PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
	PFN_vkQueuePresentKHR fpQueuePresentKHR;
public:
	VkFormat colorFormat;
	VkColorSpaceKHR colorSpace;

	VkSwapchainKHR swapChain = VK_NULL_HANDLE;

	uint32_t imageCount;
	std::vector<VkImage> images;
	std::vector<SwapChainBuffer> buffers;

	// Index of the deteced graphics and presenting device queue
	uint32_t queueNodeIndex = UINT32_MAX;

	// Creates an os specific surface
	// Tries to find a graphics and a present queue
	void initSurface(
#ifdef _WIN32
		void* platformHandle, void* platformWindow
#else
#ifdef __ANDROID__
		ANativeWindow* window
#else
		xcb_connection_t* connection, xcb_window_t window
#endif
#endif
	)
	{
		VkResult err;

		// Create surface depending on OS
#ifdef _WIN32
		VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.hinstance = (HINSTANCE)platformHandle;
		surfaceCreateInfo.hwnd = (HWND)platformWindow;
		err = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
#else
#ifdef __ANDROID__
		VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.window = window;
		err = vkCreateAndroidSurfaceKHR(instance, &surfaceCreateInfo, NULL, &surface);
#else
		VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.connection = connection;
		surfaceCreateInfo.window = window;
		err = vkCreateXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
#endif
#endif

		// Get available queue family properties
		uint32_t queueCount;
		vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
		assert(queueCount >= 1);

		std::vector<VkQueueFamilyProperties> queueProps(queueCount);
		vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());

		// Iterate over each queue to learn whether it supports presenting:
		// Find a queue with present support
		// Will be used to present the swap chain images to the windowing system
		std::vector<VkBool32> supportsPresent(queueCount);
		for (uint32_t i = 0; i < queueCount; i++)
		{
			fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &supportsPresent[i]);
		}

		// Search for a graphics and a present queue in the array of queue
		// families, try to find one that supports both
		uint32_t graphicsQueueNodeIndex = UINT32_MAX;
		uint32_t presentQueueNodeIndex = UINT32_MAX;
		for (uint32_t i = 0; i < queueCount; i++)
		{
			if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
			{
				if (graphicsQueueNodeIndex == UINT32_MAX)
				{
					graphicsQueueNodeIndex = i;
				}

				if (supportsPresent[i] == VK_TRUE)
				{
					graphicsQueueNodeIndex = i;
					presentQueueNodeIndex = i;
					break;
				}
			}
		}
		if (presentQueueNodeIndex == UINT32_MAX)
		{
			// If there's no queue that supports both present and graphics
			// try to find a separate present queue
			for (uint32_t i = 0; i < queueCount; ++i)
			{
				if (supportsPresent[i] == VK_TRUE)
				{
					presentQueueNodeIndex = i;
					break;
				}
			}
		}

		// Exit if either a graphics or a presenting queue hasn't been found
		if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
		{
			vkTools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
		}

		// todo : Add support for separate graphics and presenting queue
		if (graphicsQueueNodeIndex != presentQueueNodeIndex)
		{
			vkTools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
		}

		queueNodeIndex = graphicsQueueNodeIndex;

		// Get list of supported surface formats
		uint32_t formatCount;
		err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
		assert(!err);
		assert(formatCount > 0);

		std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
		err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfaceFormats.data());
		assert(!err);

		// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
		// there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
		if ((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
		{
			colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
		}
		else
		{
			// Always select the first available color format
			// If you need a specific format (e.g. SRGB) you'd need to
			// iterate over the list of available surface format and
			// check for it's presence
			colorFormat = surfaceFormats[0].format;
		}
		colorSpace = surfaceFormats[0].colorSpace;
	}

	// Connect to the instance und device and get all required function pointers
	void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device)
	{
		this->instance = instance;
		this->physicalDevice = physicalDevice;
		this->device = device;
		GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfaceSupportKHR);
		GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
		GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfaceFormatsKHR);
		GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfacePresentModesKHR);
		GET_DEVICE_PROC_ADDR(device, CreateSwapchainKHR);
		GET_DEVICE_PROC_ADDR(device, DestroySwapchainKHR);
		GET_DEVICE_PROC_ADDR(device, GetSwapchainImagesKHR);
		GET_DEVICE_PROC_ADDR(device, AcquireNextImageKHR);
		GET_DEVICE_PROC_ADDR(device, QueuePresentKHR);
	}

	// Create the swap chain and get images with given width and height
	void create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height)
	{
		VkResult err;
		VkSwapchainKHR oldSwapchain = swapChain;

		// Get physical device surface properties and formats
		VkSurfaceCapabilitiesKHR surfCaps;
		err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps);
		assert(!err);

		// Get available present modes
		uint32_t presentModeCount;
		err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL);
		assert(!err);
		assert(presentModeCount > 0);

		std::vector<VkPresentModeKHR> presentModes(presentModeCount);

		err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data());
		assert(!err);

		VkExtent2D swapchainExtent = {};
		// width and height are either both -1, or both not -1.
		if (surfCaps.currentExtent.width == -1)
		{
			// If the surface size is undefined, the size is set to
			// the size of the images requested.
			swapchainExtent.width = *width;
			swapchainExtent.height = *height;
		}
		else
		{
			// If the surface size is defined, the swap chain size must match
			swapchainExtent = surfCaps.currentExtent;
			*width = surfCaps.currentExtent.width;
			*height = surfCaps.currentExtent.height;
		}

		// Prefer mailbox mode if present, it's the lowest latency non-tearing present  mode
		VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
		for (size_t i = 0; i < presentModeCount; i++)
		{
			if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
			{
				swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
				break;
			}
			if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR))
			{
				swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
			}
		}

		// Determine the number of images
		uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
		if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
		{
			desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
		}

		VkSurfaceTransformFlagsKHR preTransform;
		if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
		{
			preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
		}
		else
		{
			preTransform = surfCaps.currentTransform;
		}

		VkSwapchainCreateInfoKHR swapchainCI = {};
		swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
		swapchainCI.pNext = NULL;
		swapchainCI.surface = surface;
		swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
		swapchainCI.imageFormat = colorFormat;
		swapchainCI.imageColorSpace = colorSpace;
		swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height };
		swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
		swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform;
		swapchainCI.imageArrayLayers = 1;
		swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
		swapchainCI.queueFamilyIndexCount = 0;
		swapchainCI.pQueueFamilyIndices = NULL;
		swapchainCI.presentMode = swapchainPresentMode;
		swapchainCI.oldSwapchain = oldSwapchain;
		swapchainCI.clipped = true;
		swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

		err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
		assert(!err);

		// If an existing sawp chain is re-created, destroy the old swap chain
		// This also cleans up all the presentable images
		if (oldSwapchain != VK_NULL_HANDLE)
		{
			for (uint32_t i = 0; i < imageCount; i++)
			{
				vkDestroyImageView(device, buffers[i].view, nullptr);
			}
			fpDestroySwapchainKHR(device, oldSwapchain, nullptr);
		}

		err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL);
		assert(!err);

		// Get the swap chain images
		images.resize(imageCount);
		err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, images.data());
		assert(!err);

		// Get the swap chain buffers containing the image and imageview
		buffers.resize(imageCount);
		for (uint32_t i = 0; i < imageCount; i++)
		{
			VkImageViewCreateInfo colorAttachmentView = {};
			colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
			colorAttachmentView.pNext = NULL;
			colorAttachmentView.format = colorFormat;
			colorAttachmentView.components = {
				VK_COMPONENT_SWIZZLE_R,
				VK_COMPONENT_SWIZZLE_G,
				VK_COMPONENT_SWIZZLE_B,
				VK_COMPONENT_SWIZZLE_A
			};
			colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			colorAttachmentView.subresourceRange.baseMipLevel = 0;
			colorAttachmentView.subresourceRange.levelCount = 1;
			colorAttachmentView.subresourceRange.baseArrayLayer = 0;
			colorAttachmentView.subresourceRange.layerCount = 1;
			colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
			colorAttachmentView.flags = 0;

			buffers[i].image = images[i];

			// Transform images from initial (undefined) to present layout
			vkTools::setImageLayout(
				cmdBuffer,
				buffers[i].image,
				VK_IMAGE_ASPECT_COLOR_BIT,
				VK_IMAGE_LAYOUT_UNDEFINED,
				VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);

			colorAttachmentView.image = buffers[i].image;

			err = vkCreateImageView(device, &colorAttachmentView, nullptr, &buffers[i].view);
			assert(!err);
		}
	}

	// Acquires the next image in the swap chain
	VkResult acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t *currentBuffer)
	{
		return fpAcquireNextImageKHR(device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence)nullptr, currentBuffer);
	}

	// Present the current image to the queue
	VkResult queuePresent(VkQueue queue, uint32_t currentBuffer)
	{
		VkPresentInfoKHR presentInfo = {};
		presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
		presentInfo.pNext = NULL;
		presentInfo.swapchainCount = 1;
		presentInfo.pSwapchains = &swapChain;
		presentInfo.pImageIndices = &currentBuffer;
		return fpQueuePresentKHR(queue, &presentInfo);
	}

	// Present the current image to the queue
	VkResult queuePresent(VkQueue queue, uint32_t currentBuffer, VkSemaphore waitSemaphore)
	{
		VkPresentInfoKHR presentInfo = {};
		presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
		presentInfo.pNext = NULL;
		presentInfo.swapchainCount = 1;
		presentInfo.pSwapchains = &swapChain;
		presentInfo.pImageIndices = &currentBuffer;
		if (waitSemaphore != VK_NULL_HANDLE)
		{
			presentInfo.pWaitSemaphores = &waitSemaphore;
			presentInfo.waitSemaphoreCount = 1;
		}
		return fpQueuePresentKHR(queue, &presentInfo);
	}

	// Free all Vulkan resources used by the swap chain
	void cleanup()
	{
		for (uint32_t i = 0; i < imageCount; i++)
		{
			vkDestroyImageView(device, buffers[i].view, nullptr);
		}
		fpDestroySwapchainKHR(device, swapChain, nullptr);
		vkDestroySurfaceKHR(instance, surface, nullptr);
	}

};
<commit_msg>Swap chain<commit_after>/*
* Class wrapping access to the swap chain
*
* A swap chain is a collection of framebuffers used for rendering
* The swap chain images can then presented to the windowing system
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#include <stdlib.h>
#include <string>
#include <fstream>
#include <assert.h>
#include <stdio.h>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#else
#endif

#include <vulkan/vulkan.h>
#include "vulkantools.h"

#ifdef __ANDROID__
#include "vulkanandroid.h"
#endif

typedef struct _SwapChainBuffers {
	vk::Image image;
	vk::ImageView view;
} SwapChainBuffer;

class VulkanSwapChain
{
private:
	vk::Instance instance;
	vk::Device device;
	vk::PhysicalDevice physicalDevice;
	vk::SurfaceKHR surface;
public:
	vk::Format colorFormat;
	vk::ColorSpaceKHR colorSpace;

	vk::SwapchainKHR swapChain;

	uint32_t imageCount;
	std::vector<vk::Image> images;
	std::vector<SwapChainBuffer> buffers;

	// Index of the deteced graphics and presenting device queue
	uint32_t queueNodeIndex = UINT32_MAX;

	// Creates an os specific surface
	// Tries to find a graphics and a present queue
	void initSurface(
#ifdef _WIN32
		void* platformHandle, void* platformWindow
#else
#ifdef __ANDROID__
		ANativeWindow* window
#else
		xcb_connection_t* connection, xcb_window_t window
#endif
#endif
	)
	{
		// Create surface depending on OS
#ifdef _WIN32
		vk::Win32SurfaceCreateInfoKHR surfaceCreateInfo = {};
		surfaceCreateInfo.sType = vk::StructureType::eWin32SurfaceCreateInfoKHR;
		surfaceCreateInfo.hinstance = (HINSTANCE)platformHandle;
		surfaceCreateInfo.hwnd = (HWND)platformWindow;
		surface = instance.createWin32SurfaceKHR(surfaceCreateInfo, nullptr);
#else
#ifdef __ANDROID__
		vk::AndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
		surfaceCreateInfo.sType = vk::StructureType::eAndroidSurfaceCreateInfoKHR;
		surfaceCreateInfo.window = window;
		surface = instance.createAndroidSurfaceKHR(surfaceCreateInfo, NULL);
#else
		vk::XcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
		surfaceCreateInfo.sType = vk::StructureType::eXcbSurfaceCreateInfoKHR;
		surfaceCreateInfo.connection = connection;
		surfaceCreateInfo.window = window;
		surface = instance.createXcbSurfaceKHR(surfaceCreateInfo, nullptr);
#endif
#endif

		// Get available queue family properties
		uint32_t queueCount;

		assert(queueCount >= 1);

		std::vector<vk::QueueFamilyProperties> queueProps(queueCount);
		queueProps = physicalDevice.getQueueFamilyProperties();

		// Iterate over each queue to learn whether it supports presenting:
		// Find a queue with present support
		// Will be used to present the swap chain images to the windowing system
		std::vector<vk::Bool32> supportsPresent(queueCount);
		for (uint32_t i = 0; i < queueCount; i++)
		{
			supportsPresent[i] = physicalDevice.getSurfaceSupportKHR(i, surface);
		}

		// Search for a graphics and a present queue in the array of queue
		// families, try to find one that supports both
		uint32_t graphicsQueueNodeIndex = UINT32_MAX;
		uint32_t presentQueueNodeIndex = UINT32_MAX;
		for (uint32_t i = 0; i < queueCount; i++)
		{
			if (queueProps[i].queueFlags & vk::QueueFlagBits::eGraphics)
			{
				if (graphicsQueueNodeIndex == UINT32_MAX)
				{
					graphicsQueueNodeIndex = i;
				}

				if (supportsPresent[i] == VK_TRUE)
				{
					graphicsQueueNodeIndex = i;
					presentQueueNodeIndex = i;
					break;
				}
			}
		}
		if (presentQueueNodeIndex == UINT32_MAX)
		{
			// If there's no queue that supports both present and graphics
			// try to find a separate present queue
			for (uint32_t i = 0; i < queueCount; ++i)
			{
				if (supportsPresent[i] == VK_TRUE)
				{
					presentQueueNodeIndex = i;
					break;
				}
			}
		}

		// Exit if either a graphics or a presenting queue hasn't been found
		if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
		{
			vkTools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
		}

		// todo : Add support for separate graphics and presenting queue
		if (graphicsQueueNodeIndex != presentQueueNodeIndex)
		{
			vkTools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
		}

		queueNodeIndex = graphicsQueueNodeIndex;

		// Get list of supported surface formats
		uint32_t formatCount;

		assert(formatCount > 0);

		std::vector<vk::SurfaceFormatKHR> surfaceFormats(formatCount);
		surfaceFormats = physicalDevice.getSurfaceFormatsKHR(surface);

		// If the surface format list only includes one entry with vk::Format::eUndefined,
		// there is no preferered format, so we assume vk::Format::eB8G8R8A8Unorm
		if ((formatCount == 1) && (surfaceFormats[0].format == vk::Format::eUndefined))
		{
			colorFormat = vk::Format::eB8G8R8A8Unorm;
		}
		else
		{
			// Always select the first available color format
			// If you need a specific format (e.g. SRGB) you'd need to
			// iterate over the list of available surface format and
			// check for it's presence
			colorFormat = surfaceFormats[0].format;
		}
		colorSpace = surfaceFormats[0].colorSpace;
	}

	// Connect to the instance und device and get all required function pointers
	void connect(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device)
	{
		this->instance = instance;
		this->physicalDevice = physicalDevice;
		this->device = device;
	}

	// Create the swap chain and get images with given width and height
	void create(vk::CommandBuffer cmdBuffer, uint32_t *width, uint32_t *height)
	{
		vk::SwapchainKHR oldSwapchain = swapChain;

		// Get physical device surface properties and formats
		vk::SurfaceCapabilitiesKHR surfCaps;
		surfCaps = physicalDevice.getSurfaceCapabilitiesKHR(surface).value;

		// Get available present modes
		uint32_t presentModeCount;

		assert(presentModeCount > 0);

		std::vector<vk::PresentModeKHR> presentModes(presentModeCount);

		presentModes = physicalDevice.getSurfacePresentModesKHR(surface);

		vk::Extent2D swapchainExtent = {};
		// width and height are either both -1, or both not -1.
		if (surfCaps.currentExtent.width == -1)
		{
			// If the surface size is undefined, the size is set to
			// the size of the images requested.
			swapchainExtent.width = *width;
			swapchainExtent.height = *height;
		}
		else
		{
			// If the surface size is defined, the swap chain size must match
			swapchainExtent = surfCaps.currentExtent;
			*width = surfCaps.currentExtent.width;
			*height = surfCaps.currentExtent.height;
		}

		// Prefer mailbox mode if present, it's the lowest latency non-tearing present  mode
		vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo;
		for (size_t i = 0; i < presentModeCount; i++)
		{
			if (presentModes[i] == vk::PresentModeKHR::eMailbox)
			{
				swapchainPresentMode = vk::PresentModeKHR::eMailbox;
				break;
			}
			if ((swapchainPresentMode != vk::PresentModeKHR::eMailbox) && (presentModes[i] == vk::PresentModeKHR::eImmediate))
			{
				swapchainPresentMode = vk::PresentModeKHR::eImmediate;
			}
		}

		// Determine the number of images
		uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
		if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
		{
			desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
		}

		vk::SurfaceTransformFlagBitsKHR preTransform;
		if (surfCaps.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity)
		{
			preTransform = vk::SurfaceTransformFlagBitsKHR::eIdentity;
		}
		else
		{
			preTransform = surfCaps.currentTransform;
		}

		vk::SwapchainCreateInfoKHR swapchainCI = {};
		swapchainCI.sType = vk::StructureType::eSwapchainCreateInfoKHR;
		swapchainCI.pNext = NULL;
		swapchainCI.surface = surface;
		swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
		swapchainCI.imageFormat = colorFormat;
		swapchainCI.imageColorSpace = colorSpace;
		swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height };
		swapchainCI.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
		swapchainCI.preTransform = preTransform;
		swapchainCI.imageArrayLayers = 1;
		swapchainCI.imageSharingMode = vk::SharingMode::eExclusive;
		swapchainCI.queueFamilyIndexCount = 0;
		swapchainCI.pQueueFamilyIndices = NULL;
		swapchainCI.presentMode = swapchainPresentMode;
		swapchainCI.oldSwapchain = oldSwapchain;
		swapchainCI.clipped = true;
		swapchainCI.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;

		swapChain = device.createSwapchainKHR(swapchainCI, nullptr);

		// If an existing sawp chain is re-created, destroy the old swap chain
		// This also cleans up all the presentable images
		if (oldSwapchain)
		{
			for (uint32_t i = 0; i < imageCount; i++)
			{
				device.destroyImageView(buffers[i].view, nullptr);
			}
			device.destroySwapchainKHR(oldSwapchain, nullptr);
		}

		// Get the swap chain images
		images.resize(imageCount);
		images = device.getSwapchainImagesKHR(swapChain);

		// Get the swap chain buffers containing the image and imageview
		buffers.resize(imageCount);
		for (uint32_t i = 0; i < imageCount; i++)
		{
			vk::ImageViewCreateInfo colorAttachmentView = {};
			colorAttachmentView.sType = vk::StructureType::eImageViewCreateInfo;
			colorAttachmentView.pNext = NULL;
			colorAttachmentView.format = colorFormat;
			colorAttachmentView.components = {
				vk::ComponentSwizzle::eR,
				vk::ComponentSwizzle::eG,
				vk::ComponentSwizzle::eB,
				vk::ComponentSwizzle::eA
			};
			colorAttachmentView.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
			colorAttachmentView.subresourceRange.baseMipLevel = 0;
			colorAttachmentView.subresourceRange.levelCount = 1;
			colorAttachmentView.subresourceRange.baseArrayLayer = 0;
			colorAttachmentView.subresourceRange.layerCount = 1;
			colorAttachmentView.viewType = vk::ImageViewType::e2D;

			buffers[i].image = images[i];

			// Transform images from initial (undefined) to present layout
			vkTools::setImageLayout(
				cmdBuffer,
				buffers[i].image,
				vk::ImageAspectFlagBits::eColor,
				vk::ImageLayout::eUndefined,
				vk::ImageLayout::ePresentSrcKHR);

			colorAttachmentView.image = buffers[i].image;

			buffers[i].view = device.createImageView(colorAttachmentView, nullptr);

		}
	}

	// Acquires the next image in the swap chain
	vk::Result acquireNextImage(vk::Semaphore presentCompleteSemaphore, uint32_t &currentBuffer)
	{
		auto resultValue = device.acquireNextImageKHR(swapChain, UINT64_MAX, presentCompleteSemaphore, vk::Fence());
		currentBuffer = resultValue.value;
		return resultValue.result;
	}

	// Present the current image to the queue
	vk::Result queuePresent(vk::Queue queue, uint32_t currentBuffer)
	{
		vk::PresentInfoKHR presentInfo = {};
		presentInfo.sType = vk::StructureType::ePresentInfoKHR;
		presentInfo.pNext = NULL;
		presentInfo.swapchainCount = 1;
		presentInfo.pSwapchains = &swapChain;
		presentInfo.pImageIndices = &currentBuffer;
		return queue.presentKHR(presentInfo);
	}

	// Present the current image to the queue
	vk::Result queuePresent(vk::Queue queue, uint32_t currentBuffer, vk::Semaphore waitSemaphore)
	{
		vk::PresentInfoKHR presentInfo = {};
		presentInfo.sType = vk::StructureType::ePresentInfoKHR;
		presentInfo.pNext = NULL;
		presentInfo.swapchainCount = 1;
		presentInfo.pSwapchains = &swapChain;
		presentInfo.pImageIndices = &currentBuffer;
		if (waitSemaphore)
		{
			presentInfo.pWaitSemaphores = &waitSemaphore;
			presentInfo.waitSemaphoreCount = 1;
		}
		return queue.presentKHR(presentInfo);
	}

	// Free all Vulkan resources used by the swap chain
	void cleanup()
	{
		for (uint32_t i = 0; i < imageCount; i++)
		{
			device.destroyImageView(buffers[i].view, nullptr);
		}
		device.destroySwapchainKHR(swapChain, nullptr);
		instance.destroySurfaceKHR(surface, nullptr);
	}

};
<|endoftext|>


<commit_before>#include "Test.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkRect.h"

static inline const char* boolStr(bool value) {
    return value ? "true" : "false";
}

// these are in the same order as the SkBitmap::Config enum
static const char* gConfigName[] = {
    "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
};

/** Returns -1 on success, else the x coord of the first bad pixel, return its
    value in bad
 */
typedef int (*Proc)(const void*, int width, uint32_t expected, uint32_t* bad);

static int proc_32(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
    const SkPMColor* addr = static_cast<const SkPMColor*>(ptr);
    for (int x = 0; x < w; x++) {
        if (addr[x] != expected) {
            *bad = addr[x];
            return x;
        }
    }
    return -1;
}

static int proc_16(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
    const uint16_t* addr = static_cast<const uint16_t*>(ptr);
    for (int x = 0; x < w; x++) {
        if (addr[x] != expected) {
            *bad = addr[x];
            return x;
        }
    }
    return -1;
}

static int proc_8(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
    const SkPMColor* addr = static_cast<const SkPMColor*>(ptr);
    for (int x = 0; x < w; x++) {
        if (SkGetPackedA32(addr[x]) != expected) {
            *bad = SkGetPackedA32(addr[x]);
            return x;
        }
    }
    return -1;
}

static int proc_bad(const void* ptr, int, uint32_t, uint32_t* bad) {
    *bad = 0;
    return 0;
}

static Proc find_proc(const SkBitmap& bm, SkPMColor expect32, uint16_t expect16,
                      uint8_t expect8, uint32_t* expect) {
    switch (bm.config()) {
        case SkBitmap::kARGB_8888_Config:
            *expect = expect32;
            return proc_32;
        case SkBitmap::kARGB_4444_Config:
        case SkBitmap::kRGB_565_Config:
            *expect = expect16;
            return proc_16;
        case SkBitmap::kA8_Config:
            *expect = expect8;
            return proc_8;
        default:
            *expect = 0;
            return proc_bad;
    }
}

static bool check_color(const SkBitmap& bm, SkPMColor expect32,
                        uint16_t expect16, uint8_t expect8,
                        skiatest::Reporter* reporter) {
    uint32_t expect;
    Proc proc = find_proc(bm, expect32, expect16, expect8, &expect);
    for (int y = 0; y < bm.height(); y++) {
        uint32_t bad;
        int x = proc(bm.getAddr(0, y), bm.width(), expect, &bad);
        if (x >= 0) {
            SkString str;
            str.printf("BlitRow config=%s [%d %d] expected %x got %x",
                       gConfigName[bm.config()], x, y, expect, bad);
            reporter->reportFailed(str);
            return false;
        }
    }
    return true;
}

static void TestBlitRow(skiatest::Reporter* reporter) {
    static const int W = 256;

    static const SkBitmap::Config gDstConfig[] = {
        SkBitmap::kARGB_8888_Config,
        SkBitmap::kRGB_565_Config,
//        SkBitmap::kARGB_4444_Config,
//        SkBitmap::kA8_Config,
    };

    static const struct {
        SkColor     fSrc;
        SkColor     fDst;
        SkPMColor   fResult32;
        uint16_t    fResult16;
        uint8_t     fResult8;
    } gSrcRec[] = {
        { 0,            0,          0,                                    0,      0 },
        { 0,            0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
        { 0xFFFFFFFF,   0,          SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
        { 0xFFFFFFFF,   0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
    };

    SkPaint paint;
    paint.setDither(true);

    SkBitmap srcBM;
    srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, 1);
    srcBM.allocPixels();

    for (size_t i = 0; i < SK_ARRAY_COUNT(gDstConfig); i++) {
        SkBitmap dstBM;
        dstBM.setConfig(gDstConfig[i], W, 1);
        dstBM.allocPixels();

        SkCanvas canvas(dstBM);
        for (size_t j = 0; j < SK_ARRAY_COUNT(gSrcRec); j++) {
            srcBM.eraseColor(gSrcRec[j].fSrc);
            dstBM.eraseColor(gSrcRec[j].fDst);

            for (int k = 0; k < 4; k++) {
                bool dither = (k & 1) != 0;
                bool blend = (k & 2) != 0;
                if (gSrcRec[j].fSrc != 0 && blend) {
                    // can't make a numerical promise about blending anything
                    // but 0
                 //   continue;
                }
                paint.setDither(dither);
                paint.setAlpha(blend ? 0x80 : 0xFF);
                canvas.drawBitmap(srcBM, 0, 0, &paint);
                if (!check_color(dstBM, gSrcRec[j].fResult32, gSrcRec[j].fResult16,
                                 gSrcRec[j].fResult8, reporter)) {
                    SkDebugf("--- src index %d dither %d blend %d\n", j, dither, blend);
                }
            }
        }
    }
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("BlitRow", TestBlitRowClass, TestBlitRow)
<commit_msg>refresh from skia/trunk<commit_after>#include "Test.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkGradientShader.h"
#include "SkRect.h"

static inline const char* boolStr(bool value) {
    return value ? "true" : "false";
}

// these are in the same order as the SkBitmap::Config enum
static const char* gConfigName[] = {
    "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
};

/** Returns -1 on success, else the x coord of the first bad pixel, return its
    value in bad
 */
typedef int (*Proc)(const void*, int width, uint32_t expected, uint32_t* bad);

static int proc_32(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
    const SkPMColor* addr = static_cast<const SkPMColor*>(ptr);
    for (int x = 0; x < w; x++) {
        if (addr[x] != expected) {
            *bad = addr[x];
            return x;
        }
    }
    return -1;
}

static int proc_16(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
    const uint16_t* addr = static_cast<const uint16_t*>(ptr);
    for (int x = 0; x < w; x++) {
        if (addr[x] != expected) {
            *bad = addr[x];
            return x;
        }
    }
    return -1;
}

static int proc_8(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
    const SkPMColor* addr = static_cast<const SkPMColor*>(ptr);
    for (int x = 0; x < w; x++) {
        if (SkGetPackedA32(addr[x]) != expected) {
            *bad = SkGetPackedA32(addr[x]);
            return x;
        }
    }
    return -1;
}

static int proc_bad(const void* ptr, int, uint32_t, uint32_t* bad) {
    *bad = 0;
    return 0;
}

static Proc find_proc(const SkBitmap& bm, SkPMColor expect32, uint16_t expect16,
                      uint8_t expect8, uint32_t* expect) {
    switch (bm.config()) {
        case SkBitmap::kARGB_8888_Config:
            *expect = expect32;
            return proc_32;
        case SkBitmap::kARGB_4444_Config:
        case SkBitmap::kRGB_565_Config:
            *expect = expect16;
            return proc_16;
        case SkBitmap::kA8_Config:
            *expect = expect8;
            return proc_8;
        default:
            *expect = 0;
            return proc_bad;
    }
}

static bool check_color(const SkBitmap& bm, SkPMColor expect32,
                        uint16_t expect16, uint8_t expect8,
                        skiatest::Reporter* reporter) {
    uint32_t expect;
    Proc proc = find_proc(bm, expect32, expect16, expect8, &expect);
    for (int y = 0; y < bm.height(); y++) {
        uint32_t bad;
        int x = proc(bm.getAddr(0, y), bm.width(), expect, &bad);
        if (x >= 0) {
            SkString str;
            str.printf("BlitRow config=%s [%d %d] expected %x got %x",
                       gConfigName[bm.config()], x, y, expect, bad);
            reporter->reportFailed(str);
            return false;
        }
    }
    return true;
}

// Make sure our blits always map src==0 to a noop, and src==FF to full opaque
static void test_00_FF(skiatest::Reporter* reporter) {
    static const int W = 256;

    static const SkBitmap::Config gDstConfig[] = {
        SkBitmap::kARGB_8888_Config,
        SkBitmap::kRGB_565_Config,
//        SkBitmap::kARGB_4444_Config,
//        SkBitmap::kA8_Config,
    };

    static const struct {
        SkColor     fSrc;
        SkColor     fDst;
        SkPMColor   fResult32;
        uint16_t    fResult16;
        uint8_t     fResult8;
    } gSrcRec[] = {
        { 0,            0,          0,                                    0,      0 },
        { 0,            0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
        { 0xFFFFFFFF,   0,          SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
        { 0xFFFFFFFF,   0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
    };

    SkPaint paint;

    SkBitmap srcBM;
    srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, 1);
    srcBM.allocPixels();

    for (size_t i = 0; i < SK_ARRAY_COUNT(gDstConfig); i++) {
        SkBitmap dstBM;
        dstBM.setConfig(gDstConfig[i], W, 1);
        dstBM.allocPixels();

        SkCanvas canvas(dstBM);
        for (size_t j = 0; j < SK_ARRAY_COUNT(gSrcRec); j++) {
            srcBM.eraseColor(gSrcRec[j].fSrc);
            dstBM.eraseColor(gSrcRec[j].fDst);

            for (int k = 0; k < 4; k++) {
                bool dither = (k & 1) != 0;
                bool blend = (k & 2) != 0;
                if (gSrcRec[j].fSrc != 0 && blend) {
                    // can't make a numerical promise about blending anything
                    // but 0
                 //   continue;
                }
                paint.setDither(dither);
                paint.setAlpha(blend ? 0x80 : 0xFF);
                canvas.drawBitmap(srcBM, 0, 0, &paint);
                if (!check_color(dstBM, gSrcRec[j].fResult32, gSrcRec[j].fResult16,
                                 gSrcRec[j].fResult8, reporter)) {
                    SkDebugf("--- src index %d dither %d blend %d\n", j, dither, blend);
                }
            }
        }
    }
}

///////////////////////////////////////////////////////////////////////////////

struct Mesh {
    SkPoint     fPts[4];
    uint16_t    fIndices[6];

    Mesh(const SkBitmap& bm, SkPaint* paint) {
        const SkScalar w = SkIntToScalar(bm.width());
        const SkScalar h = SkIntToScalar(bm.height());
        fPts[0].set(0, 0);
        fPts[1].set(w, 0);
        fPts[2].set(w, h);
        fPts[3].set(0, h);
        SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
                                                   SkShader::kClamp_TileMode);
        paint->setShader(s)->unref();

    }

    void draw(SkCanvas* canvas, SkPaint* paint) {
        canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, fPts, fPts,
                             NULL, NULL, NULL, 0, *paint);
    }
};

#include "SkImageEncoder.h"
static void save_bm(const SkBitmap& bm, const char name[]) {
    SkImageEncoder::EncodeFile(name, bm, SkImageEncoder::kPNG_Type, 100);
}

static bool gOnce;

// Make sure our blits are invariant with the width of the blit (i.e. that
// special case for 8 at a time have the same results as narrower blits)
static void test_diagonal(skiatest::Reporter* reporter) {
    static const int W = 64;
    static const int H = W;

    static const SkBitmap::Config gDstConfig[] = {
        SkBitmap::kARGB_8888_Config,
        SkBitmap::kRGB_565_Config,
        //        SkBitmap::kARGB_4444_Config,
        //        SkBitmap::kA8_Config,
    };

    static const SkColor gDstBG[] = { 0, 0xFFFFFFFF };

    SkPaint paint;

    SkBitmap srcBM;
    srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, H);
    srcBM.allocPixels();
    SkRect srcR = { 0, 0, srcBM.width(), srcBM.height() };

    // cons up a mesh to draw the bitmap with
    Mesh mesh(srcBM, &paint);

    for (size_t i = 0; i < SK_ARRAY_COUNT(gDstConfig); i++) {
        SkBitmap dstBM0, dstBM1;
        dstBM0.setConfig(gDstConfig[i], W, H);
        dstBM1.setConfig(gDstConfig[i], W, H);
        dstBM0.allocPixels();
        dstBM1.allocPixels();

        SkCanvas canvas0(dstBM0);
        SkCanvas canvas1(dstBM1);
        SkColor bgColor;

        for (size_t j = 0; j < SK_ARRAY_COUNT(gDstBG); j++) {
            bgColor = gDstBG[j];

            for (int c = 0; c <= 0xFF; c++) {
                srcBM.eraseARGB(0xFF, c, c, c);

                for (int k = 0; k < 4; k++) {
                    bool dither = (k & 1) != 0;
                    uint8_t alpha = (k & 2) ? 0x80 : 0xFF;
                    paint.setDither(dither);
                    paint.setAlpha(alpha);

                    dstBM0.eraseColor(bgColor);
                    dstBM1.eraseColor(bgColor);

                    canvas0.drawRect(srcR, paint);
                    mesh.draw(&canvas1, &paint);

                    if (!gOnce && false) {
                        save_bm(dstBM0, "drawBitmap.png");
                        save_bm(dstBM1, "drawMesh.png");
                        gOnce = true;
                    }

                    if (memcmp(dstBM0.getPixels(), dstBM1.getPixels(), dstBM0.getSize())) {
                        SkString str;
                        str.printf("Diagonal config=%s bg=0x%x dither=%d alpha=0x%x src=0x%x",
                                   gConfigName[gDstConfig[i]], bgColor, dither, alpha, c);
                        reporter->reportFailed(str);
                    }
                }
            }
        }
    }
}

static void TestBlitRow(skiatest::Reporter* reporter) {
    test_00_FF(reporter);
    test_diagonal(reporter);
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("BlitRow", TestBlitRowClass, TestBlitRow)
<|endoftext|>


<commit_before>/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   JGS, Jim Smith    , University of Colorado, jgsmith@pizero.colorado.edu *
 * History:
 *   15-Aug-2002 JGS Created initial version
 *   11-Sep-2002 JGS Mods to introduce mu (Mirna van Hoek, JGS, Nick Danielson)
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California,         *
 *                          University of Colorado                           *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// Implement standard CP physics model with S and C (no mention of lambda)
// Suitably stolen and modified from RooBCPEffDecay
// END_HTML
//

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include "RooRealVar.h"
#include "RooRandom.h"
#include "RooBCPGenDecay.h"
#include "RooRealIntegral.h"

using namespace std;

ClassImp(RooBCPGenDecay)
;

//_____________________________________________________________________________
RooBCPGenDecay::RooBCPGenDecay(const char *name, const char *title,
			       RooRealVar& t, RooAbsCategory& tag,
			       RooAbsReal& tau, RooAbsReal& dm,
			       RooAbsReal& avgMistag,
			       RooAbsReal& a, RooAbsReal& b,
			       RooAbsReal& delMistag,
                               RooAbsReal& mu,
			       const RooResolutionModel& model, DecayType type) :
  RooAbsAnaConvPdf(name,title,model,t),
  _avgC("C","Coefficient of cos term",this,a),
  _avgS("S","Coefficient of cos term",this,b),
  _avgMistag("avgMistag","Average mistag rate",this,avgMistag),
  _delMistag("delMistag","Delta mistag rate",this,delMistag),
  _mu("mu","Tagg efficiency difference",this,mu),
  _t("t","time",this,t),
  _tau("tau","decay time",this,tau),
  _dm("dm","mixing frequency",this,dm),
  _tag("tag","CP state",this,tag),
  _genB0Frac(0),
  _type(type)
{
  // Constructor
  switch(type) {
  case SingleSided:
    _basisExp = declareBasis("exp(-@0/@1)",RooArgList(tau,dm)) ;
    _basisSin = declareBasis("exp(-@0/@1)*sin(@0*@2)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case Flipped:
    _basisExp = declareBasis("exp(@0)/@1)",RooArgList(tau,dm)) ;
    _basisSin = declareBasis("exp(@0/@1)*sin(@0*@2)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case DoubleSided:
    _basisExp = declareBasis("exp(-abs(@0)/@1)",RooArgList(tau,dm)) ;
    _basisSin = declareBasis("exp(-abs(@0)/@1)*sin(@0*@2)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-abs(@0)/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  }
}

//_____________________________________________________________________________
RooBCPGenDecay::RooBCPGenDecay(const RooBCPGenDecay& other, const char* name) :
  RooAbsAnaConvPdf(other,name),
  _avgC("C",this,other._avgC),
  _avgS("S",this,other._avgS),
  _avgMistag("avgMistag",this,other._avgMistag),
  _delMistag("delMistag",this,other._delMistag),
  _mu("mu",this,other._mu),
  _t("t",this,other._t),
  _tau("tau",this,other._tau),
  _dm("dm",this,other._dm),
  _tag("tag",this,other._tag),
  _genB0Frac(other._genB0Frac),
  _type(other._type),
  _basisExp(other._basisExp),
  _basisSin(other._basisSin),
  _basisCos(other._basisCos)
{
  // Copy constructor
}

//_____________________________________________________________________________
RooBCPGenDecay::~RooBCPGenDecay()
{
  // Destructor
}

//_____________________________________________________________________________
Double_t RooBCPGenDecay::coefficient(Int_t basisIndex) const
{
  // B0    : _tag = +1
  // B0bar : _tag = -1

  if (basisIndex==_basisExp) {
    //exp term: (1 -/+ dw + mu*_tag*w)
    return (1 - _tag*_delMistag + _mu*_tag*(1. - 2.*_avgMistag)) ;
    // =    1 + _tag*deltaDil/2 + _mu*avgDil
  }

  if (basisIndex==_basisSin) {
    //sin term: (+/- (1-2w) + _mu*(1 -/+ delw))*S
    return (_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgS ;
    // =   (_tag*avgDil + _mu*(1 + tag*deltaDil/2)) * S
  }

  if (basisIndex==_basisCos) {
    //cos term: -(+/- (1-2w) + _mu*(1 -/+ delw))*C
    return -1.*(_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgC ;
    // =   -(_tag*avgDil + _mu*(1 + _tag*deltaDil/2) )* C
  }

  return 0 ;
}

//_____________________________________________________________________________
Int_t RooBCPGenDecay::getCoefAnalyticalIntegral(Int_t /*code*/, RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
{
  if (rangeName) return 0 ;
  if (matchArgs(allVars,analVars,_tag)) return 1 ;
  return 0 ;
}

//_____________________________________________________________________________
Double_t RooBCPGenDecay::coefAnalyticalIntegral(Int_t basisIndex, Int_t code, const char* /*rangeName*/) const
{
  switch(code) {
    // No integration
  case 0: return coefficient(basisIndex) ;

    // Integration over 'tag'
  case 1:
    if (basisIndex==_basisExp) {
      return 2 ;
    }

    if (basisIndex==_basisSin) {
      return 2*_mu*_avgS ;
    }
    if (basisIndex==_basisCos) {
      return -2*_mu*_avgC ;
    }
    break ;

  default:
    assert(0) ;
  }

  return 0 ;
}

//_____________________________________________________________________________
Int_t RooBCPGenDecay::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK) const
{
  if (staticInitOK) {
    if (matchArgs(directVars,generateVars,_t,_tag)) return 2 ;
  }
  if (matchArgs(directVars,generateVars,_t)) return 1 ;
  return 0 ;
}

//_____________________________________________________________________________
void RooBCPGenDecay::initGenerator(Int_t code)
{
  if (code==2) {
    // Calculate the fraction of mixed events to generate
    Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_tag.arg())).getVal() ;
    _tag = 1 ;
    Double_t b0Int = RooRealIntegral("mixInt","mix integral",*this,RooArgSet(_t.arg())).getVal() ;
    _genB0Frac = b0Int/sumInt ;
  }
}

//_____________________________________________________________________________
void RooBCPGenDecay::generateEvent(Int_t code)
{
  // Generate mix-state dependent
  if (code==2) {
    Double_t rand = RooRandom::uniform() ;
    _tag = (rand<=_genB0Frac) ? 1 : -1 ;
  }

  // Generate delta-t dependent
  while(1) {
    Double_t rand = RooRandom::uniform() ;
    Double_t tval(0) ;

    switch(_type) {
    case SingleSided:
      tval = -_tau*log(rand);
      break ;
    case Flipped:
      tval= +_tau*log(rand);
      break ;
    case DoubleSided:
      tval = (rand<=0.5) ? -_tau*log(2*rand) : +_tau*log(2*(rand-0.5)) ;
      break ;
    }

    // Accept event if T is in generated range
    Double_t maxDil = 1.0 ;
// 2 in next line is conservative and inefficient - allows for delMistag=1!
    Double_t maxAcceptProb = 2 + fabs(maxDil*_avgS) + fabs(maxDil*_avgC);
    Double_t acceptProb    = (1-_tag*_delMistag + _mu*_tag*(1. - 2.*_avgMistag))
                           + (_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgS*sin(_dm*tval)
                           - (_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgC*cos(_dm*tval);

    Bool_t accept = maxAcceptProb*RooRandom::uniform() < acceptProb ? kTRUE : kFALSE ;

    if (tval<_t.max() && tval>_t.min() && accept) {
      _t = tval ;
      break ;
    }
  }

}

<commit_msg>patch to RooBCPGenDecay by Paul Seyfert: fix titles of variables, remove superfluous include directives<commit_after>/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   JGS, Jim Smith    , University of Colorado, jgsmith@pizero.colorado.edu *
 * History:
 *   15-Aug-2002 JGS Created initial version
 *   11-Sep-2002 JGS Mods to introduce mu (Mirna van Hoek, JGS, Nick Danielson)
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California,         *
 *                          University of Colorado                           *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// Implement standard CP physics model with S and C (no mention of lambda)
// Suitably stolen and modified from RooBCPEffDecay
// END_HTML
//

#include "RooRealVar.h"
#include "RooRandom.h"
#include "RooBCPGenDecay.h"
#include "RooRealIntegral.h"

using namespace std;

ClassImp(RooBCPGenDecay)
;

//_____________________________________________________________________________
RooBCPGenDecay::RooBCPGenDecay(const char *name, const char *title,
			       RooRealVar& t, RooAbsCategory& tag,
			       RooAbsReal& tau, RooAbsReal& dm,
			       RooAbsReal& avgMistag,
			       RooAbsReal& a, RooAbsReal& b,
			       RooAbsReal& delMistag,
                               RooAbsReal& mu,
			       const RooResolutionModel& model, DecayType type) :
  RooAbsAnaConvPdf(name,title,model,t),
  _avgC("C","Coefficient of cos term",this,a),
  _avgS("S","Coefficient of sin term",this,b),
  _avgMistag("avgMistag","Average mistag rate",this,avgMistag),
  _delMistag("delMistag","Delta mistag rate",this,delMistag),
  _mu("mu","Tagg efficiency difference",this,mu),
  _t("t","time",this,t),
  _tau("tau","decay time",this,tau),
  _dm("dm","mixing frequency",this,dm),
  _tag("tag","CP state",this,tag),
  _genB0Frac(0),
  _type(type)
{
  // Constructor
  switch(type) {
  case SingleSided:
    _basisExp = declareBasis("exp(-@0/@1)",RooArgList(tau,dm)) ;
    _basisSin = declareBasis("exp(-@0/@1)*sin(@0*@2)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case Flipped:
    _basisExp = declareBasis("exp(@0)/@1)",RooArgList(tau,dm)) ;
    _basisSin = declareBasis("exp(@0/@1)*sin(@0*@2)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(@0/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  case DoubleSided:
    _basisExp = declareBasis("exp(-abs(@0)/@1)",RooArgList(tau,dm)) ;
    _basisSin = declareBasis("exp(-abs(@0)/@1)*sin(@0*@2)",RooArgList(tau,dm)) ;
    _basisCos = declareBasis("exp(-abs(@0)/@1)*cos(@0*@2)",RooArgList(tau,dm)) ;
    break ;
  }
}

//_____________________________________________________________________________
RooBCPGenDecay::RooBCPGenDecay(const RooBCPGenDecay& other, const char* name) :
  RooAbsAnaConvPdf(other,name),
  _avgC("C",this,other._avgC),
  _avgS("S",this,other._avgS),
  _avgMistag("avgMistag",this,other._avgMistag),
  _delMistag("delMistag",this,other._delMistag),
  _mu("mu",this,other._mu),
  _t("t",this,other._t),
  _tau("tau",this,other._tau),
  _dm("dm",this,other._dm),
  _tag("tag",this,other._tag),
  _genB0Frac(other._genB0Frac),
  _type(other._type),
  _basisExp(other._basisExp),
  _basisSin(other._basisSin),
  _basisCos(other._basisCos)
{
  // Copy constructor
}

//_____________________________________________________________________________
RooBCPGenDecay::~RooBCPGenDecay()
{
  // Destructor
}

//_____________________________________________________________________________
Double_t RooBCPGenDecay::coefficient(Int_t basisIndex) const
{
  // B0    : _tag = +1
  // B0bar : _tag = -1

  if (basisIndex==_basisExp) {
    //exp term: (1 -/+ dw + mu*_tag*w)
    return (1 - _tag*_delMistag + _mu*_tag*(1. - 2.*_avgMistag)) ;
    // =    1 + _tag*deltaDil/2 + _mu*avgDil
  }

  if (basisIndex==_basisSin) {
    //sin term: (+/- (1-2w) + _mu*(1 -/+ delw))*S
    return (_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgS ;
    // =   (_tag*avgDil + _mu*(1 + tag*deltaDil/2)) * S
  }

  if (basisIndex==_basisCos) {
    //cos term: -(+/- (1-2w) + _mu*(1 -/+ delw))*C
    return -1.*(_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgC ;
    // =   -(_tag*avgDil + _mu*(1 + _tag*deltaDil/2) )* C
  }

  return 0 ;
}

//_____________________________________________________________________________
Int_t RooBCPGenDecay::getCoefAnalyticalIntegral(Int_t /*code*/, RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const
{
  if (rangeName) return 0 ;
  if (matchArgs(allVars,analVars,_tag)) return 1 ;
  return 0 ;
}

//_____________________________________________________________________________
Double_t RooBCPGenDecay::coefAnalyticalIntegral(Int_t basisIndex, Int_t code, const char* /*rangeName*/) const
{
  switch(code) {
    // No integration
  case 0: return coefficient(basisIndex) ;

    // Integration over 'tag'
  case 1:
    if (basisIndex==_basisExp) {
      return 2 ;
    }

    if (basisIndex==_basisSin) {
      return 2*_mu*_avgS ;
    }
    if (basisIndex==_basisCos) {
      return -2*_mu*_avgC ;
    }
    break ;

  default:
    assert(0) ;
  }

  return 0 ;
}

//_____________________________________________________________________________
Int_t RooBCPGenDecay::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK) const
{
  if (staticInitOK) {
    if (matchArgs(directVars,generateVars,_t,_tag)) return 2 ;
  }
  if (matchArgs(directVars,generateVars,_t)) return 1 ;
  return 0 ;
}

//_____________________________________________________________________________
void RooBCPGenDecay::initGenerator(Int_t code)
{
  if (code==2) {
    // Calculate the fraction of mixed events to generate
    Double_t sumInt = RooRealIntegral("sumInt","sum integral",*this,RooArgSet(_t.arg(),_tag.arg())).getVal() ;
    _tag = 1 ;
    Double_t b0Int = RooRealIntegral("mixInt","mix integral",*this,RooArgSet(_t.arg())).getVal() ;
    _genB0Frac = b0Int/sumInt ;
  }
}

//_____________________________________________________________________________
void RooBCPGenDecay::generateEvent(Int_t code)
{
  // Generate mix-state dependent
  if (code==2) {
    Double_t rand = RooRandom::uniform() ;
    _tag = (rand<=_genB0Frac) ? 1 : -1 ;
  }

  // Generate delta-t dependent
  while(1) {
    Double_t rand = RooRandom::uniform() ;
    Double_t tval(0) ;

    switch(_type) {
    case SingleSided:
      tval = -_tau*log(rand);
      break ;
    case Flipped:
      tval= +_tau*log(rand);
      break ;
    case DoubleSided:
      tval = (rand<=0.5) ? -_tau*log(2*rand) : +_tau*log(2*(rand-0.5)) ;
      break ;
    }

    // Accept event if T is in generated range
    Double_t maxDil = 1.0 ;
// 2 in next line is conservative and inefficient - allows for delMistag=1!
    Double_t maxAcceptProb = 2 + fabs(maxDil*_avgS) + fabs(maxDil*_avgC);
    Double_t acceptProb    = (1-_tag*_delMistag + _mu*_tag*(1. - 2.*_avgMistag))
                           + (_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgS*sin(_dm*tval)
                           - (_tag*(1-2*_avgMistag) + _mu*(1. - _tag*_delMistag))*_avgC*cos(_dm*tval);

    Bool_t accept = maxAcceptProb*RooRandom::uniform() < acceptProb ? kTRUE : kFALSE ;

    if (tval<_t.max() && tval>_t.min() && accept) {
      _t = tval ;
      break ;
    }
  }

}

<|endoftext|>


<commit_before>#include <iostream>

#include "BigInteger.hpp"

using namespace std;

int main(int argc, char* argv[]) {

	// calculate the millionth fibonacci number //
	// should take about 90s

	BigInteger num1 = BigInteger(0,11000);
	BigInteger num2 = BigInteger(1,11000);
	BigInteger num3 = BigInteger(0,11000);

	cout << "calculating...\n";
	for(unsigned long long i = 2;i <= 1000000;++i) {
		num3 = num1;
		num3 += num2;
		num1 = num2;
		num2 = num3;
	}
	cout << "\tdone.\n";

	cout << "generating decimal...\n";
	num3.decPrint();
	cout << "\n";

	return 0;
}
<commit_msg>updated sample driver<commit_after>#include <iostream>

#include "BigInteger.hpp"

using namespace std;

int main(int argc, char* argv[]) {

	// calculate the millionth fibonacci number //
	// should take about 90s

	BigInteger num1 = BigInteger(0,11000);
	BigInteger num2 = BigInteger(1,11000);
	BigInteger num3 = BigInteger(0,11000);

	cout << "calculating...\n";
	for(unsigned long long i = 2;i <= 1000000;++i) {
		num3 = num1;
		num3 += num2;
		num1 = num2;
		num2 = num3;
	}
	cout << "\tdone.\n";

	cout << "generating decimal...\n";
	cout << num3 << "\n";

	return 0;
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2002 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cssysdef.h"
#include "csutil/sysfunc.h"
#include "qint.h"
#include "qsqrt.h"
#include "csgeom/math3d.h"
#include "csgeom/tri.h"
#include "csgeom/bsptree.h"

//---------------------------------------------------------------------------

csBlockAllocator<csBSPTree> csBSPTree::tree_nodes (1000);

csBSPTree::csBSPTree ()
{
  child1 = 0;
  child2 = 0;
  split_poly = -1;
}

csBSPTree::~csBSPTree ()
{
  Clear ();
}

void csBSPTree::Clear ()
{
  if (child1)
  {
    tree_nodes.Free (child1);
    child1 = 0;
  }
  if (child2)
  {
    tree_nodes.Free (child2);
    child2 = 0;
  }
}

int csBSPTree::FindBestSplitter (csTriangle* triangles, csPlane3* planes,
	int num_triangles, csVector3* vertices)
{
  int i, j;
  for (i = 0 ; i < num_triangles ; i++)
  {
    int cnt_splits = 0;
    int cnt_left = 0;
    int cnt_right = 0;
    csPlane3& pl = planes[i];
    for (j = 0 ; j < num_triangles ; j++)
      if (i != j)
      {
        csTriangle& trj = triangles[j];
        int cla, clb, clc;
        cla = SIGN (pl.Classify (vertices[trj.a]));
        clb = SIGN (pl.Classify (vertices[trj.b]));
        clc = SIGN (pl.Classify (vertices[trj.c]));
      }
  }
  return -1;
}

void csBSPTree::Build (csTriangle* triangles, int num_triangles,
	csVector3* vertices)
{
  csPlane3* planes = new csPlane3[num_triangles];
  int i;
  for (i = 0 ; i < num_triangles ; i++)
  {
    csTriangle& t = triangles[i];
    planes[i].Set (vertices[t.a], vertices[t.b], vertices[t.c]);
  }

}

void csBSPTree::Front2Back (const csVector3& pos, csBSPTreeVisitFunc* func)
{
}

<commit_msg>Forgot to commit.<commit_after>/*
    Copyright (C) 2002 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cssysdef.h"
#include "csutil/sysfunc.h"
#include "qint.h"
#include "qsqrt.h"
#include "csgeom/math3d.h"
#include "csgeom/tri.h"
#include "csgeom/bsptree.h"

//---------------------------------------------------------------------------

csBlockAllocator<csBSPTree> csBSPTree::tree_nodes (1000);
csDirtyAccessArray<int> csBSPTree::b2f_array;

csBSPTree::csBSPTree ()
{
  child1 = 0;
  child2 = 0;
}

csBSPTree::~csBSPTree ()
{
  Clear ();
}

void csBSPTree::Clear ()
{
  if (child1)
  {
    tree_nodes.Free (child1);
    child1 = 0;
  }
  if (child2)
  {
    tree_nodes.Free (child2);
    child2 = 0;
  }
}

int csBSPTree::FindBestSplitter (csTriangle* triangles, csPlane3* planes,
	int num_triangles, csVector3* vertices,
	const csArray<int>& triidx)
{
  int i, j;
  float mincost = 1000000.0;
  int minidx = -1;
  for (i = 0 ; i < triidx.Length () ; i++)
  {
    int cnt_splits = 0;
    int cnt_left = 0;
    int cnt_right = 0;
    csPlane3& pl = planes[triidx[i]];
    for (j = 0 ; j < triidx.Length () ; j++)
      if (i != j)
      {
        csTriangle& trj = triangles[triidx[j]];
	float fcla, fclb, fclc;
        fcla = pl.Classify (vertices[trj.a]);
        fclb = pl.Classify (vertices[trj.b]);
        fclc = pl.Classify (vertices[trj.c]);
	int cla, clb, clc;
	if (fcla < -EPSILON) cla = -1;
	else if (fcla > EPSILON) cla = 1;
	else cla = 0;
	if (fclb < -EPSILON) clb = -1;
	else if (fclb > EPSILON) clb = 1;
	else clb = 0;
	if (fclc < -EPSILON) clc = -1;
	else if (fclc > EPSILON) clc = 1;
	else clc = 0;
	if ((cla == -clb && cla != 0) ||
	    (cla == -clc && cla != 0) ||
	    (clb == -clc && clb != 0))
	{
	  // There is a split.
	  cnt_splits++;
	}
	else
	{
	  if (cla == -1 || clb == -1 || clc == -1)
	    cnt_left++;
	  else if (cla == 1 || clb == 1 || clc == 1)
	    cnt_right++;
	}
      }
    float split = float (cnt_splits) / float (triidx.Length ());
    float balance = float (ABS (cnt_left-cnt_right)) / float (triidx.Length ());
    float cost = 10.0 * split + balance;
    if (cost < mincost)
    {
      minidx = i;
      mincost = cost;
    }
  }
  return minidx;
}

void csBSPTree::Build (csTriangle* triangles, csPlane3* planes,
	int num_triangles, csVector3* vertices,
	const csArray<int>& triidx)
{
  CS_ASSERT (triidx.Length () > 0);
  if (triidx.Length () == 1)
  {
    splitters.Push (triidx[0]);
    return;
  }

  int idx = FindBestSplitter (triangles, planes, num_triangles, vertices,
  	triidx);
  CS_ASSERT (idx >= 0);
  splitters.Push (triidx[idx]);

  csArray<int> left;
  csArray<int> right;
  int i;
  split_plane = planes[triidx[idx]];
  for (i = 0 ; i < triidx.Length () ; i++)
    if (i != idx)
    {
      int idxi = triidx[i];
      csTriangle& trj = triangles[idxi];
      float fcla, fclb, fclc;
      fcla = split_plane.Classify (vertices[trj.a]);
      fclb = split_plane.Classify (vertices[trj.b]);
      fclc = split_plane.Classify (vertices[trj.c]);
      int cla, clb, clc;
      if (fcla < -EPSILON) cla = -1;
      else if (fcla > EPSILON) cla = 1;
      else cla = 0;
      if (fclb < -EPSILON) clb = -1;
      else if (fclb > EPSILON) clb = 1;
      else clb = 0;
      if (fclc < -EPSILON) clc = -1;
      else if (fclc > EPSILON) clc = 1;
      else clc = 0;
      if ((cla == -clb && cla != 0) ||
	  (cla == -clc && cla != 0) ||
	  (clb == -clc && clb != 0))
      {
	// There is a split.
	left.Push (idxi);
	right.Push (idxi);
      }
      else
      {
	if (cla == -1 || clb == -1 || clc == -1)
	  left.Push (idxi);
	else if (cla == 1 || clb == 1 || clc == 1)
	  right.Push (idxi);
        else
	  splitters.Push (idxi);
      }
    }
  if (left.Length () > 0)
  {
    child1 = tree_nodes.Alloc ();
    child1->Build (triangles, planes, num_triangles, vertices, left);
  }
  if (right.Length () > 0)
  {
    child2 = tree_nodes.Alloc ();
    child2->Build (triangles, planes, num_triangles, vertices, right);
  }
}

void csBSPTree::Build (csTriangle* triangles, int num_triangles,
	csVector3* vertices)
{
  csPlane3* planes = new csPlane3[num_triangles];
  csArray<int> triidx;
  int i;
  for (i = 0 ; i < num_triangles ; i++)
  {
    csTriangle& t = triangles[i];
    planes[i].Set (vertices[t.a], vertices[t.b], vertices[t.c]);
    triidx.Push (i);
  }

  Build (triangles, planes, num_triangles, vertices, triidx);
}

void csBSPTree::Back2Front (const csVector3& pos, csDirtyAccessArray<int>& arr,
  	csSet<int>& used_indices)
{
  float cl = split_plane.Classify (pos);

  if (cl < 0)
  {
    if (child2) child2->Back2Front (pos, arr, used_indices);
  }
  else
  {
    if (child1) child1->Back2Front (pos, arr, used_indices);
  }

  int i;
  for (i = 0 ; i < splitters.Length () ; i++)
    if (!used_indices.In (splitters[i]))
    {
      used_indices.AddNoTest (splitters[i]);
      arr.Push (splitters[i]);
    }

  if (cl < 0)
  {
    if (child1) child1->Back2Front (pos, arr, used_indices);
  }
  else
  {
    if (child2) child2->Back2Front (pos, arr, used_indices);
  }
}

const csDirtyAccessArray<int>& csBSPTree::Back2Front (const csVector3& pos)
{
  b2f_array.Empty ();
  csSet<int> used_indices;
  Back2Front (pos, b2f_array, used_indices);
  return b2f_array;
}

<|endoftext|>


<commit_before><commit_msg>convert inlines as well<commit_after><|endoftext|>