postExtract = postExtractLibpng),
GitRepo(
"https://github.com/KhronosGroup/SPIRV-Tools.git",
- "f18e1f293b7cf8f24a42587b48f35bc49912a5dd",
+ "38036a7203ca604c0f25b0dc33da169ac58e2900",
"spirv-tools"),
GitRepo(
"https://github.com/KhronosGroup/glslang.git",
"glslang"),
GitRepo(
"https://github.com/KhronosGroup/SPIRV-Headers.git",
- "e4e22fd832810c45f46d542c67910b0c6bf4ca2d",
+ "bd47a9abaefac00be692eae677daed1b977e625c",
"spirv-headers"),
]
#include "deThread.h"
#include "deThreadLocal.h"
+#include "deMutex.h"
namespace glslang
{
return deThreadLocal_get((deThreadLocal)nIndex);
}
-// Global lock - not used
+// Global lock
+
+static deMutex s_globalLock = 0;
void InitGlobalLock (void)
{
+ DE_ASSERT(s_globalLock == 0);
+ s_globalLock = deMutex_create(DE_NULL);
}
void GetGlobalLock (void)
{
+ deMutex_lock(s_globalLock);
}
void ReleaseGlobalLock (void)
{
+ deMutex_unlock(s_globalLock);
}
// Threading
#include "tcuFormatUtil.hpp"
#include "deFilePath.hpp"
#include "deStringUtil.hpp"
+#include "deDirectoryIterator.hpp"
#include "deString.h"
#include "deInt32.h"
+#include "deFile.h"
#include <sstream>
#include <fstream>
namespace
{
+string getProgramFileName (deUint32 index)
+{
+ return de::toString(tcu::toHex(index)) + ".spv";
+}
+
string getProgramPath (const std::string& dirName, deUint32 index)
{
- return de::FilePath::join(dirName, de::toString(tcu::toHex(index)) + ".spv").getPath();
+ return de::FilePath::join(dirName, getProgramFileName(index)).getPath();
+}
+
+bool isHexChr (char c)
+{
+ return de::inRange(c, '0', '9') || de::inRange(c, 'a', 'f') || de::inRange(c, 'A', 'F');
+}
+
+bool isProgramFileName (const std::string& name)
+{
+ // 0x + 00000000 + .spv
+ if (name.length() != (2 + 8 + 4))
+ return false;
+
+ if (name[0] != '0' ||
+ name[1] != 'x' ||
+ name[10] != '.' ||
+ name[11] != 's' ||
+ name[12] != 'p' ||
+ name[13] != 'v')
+ return false;
+
+ for (size_t ndx = 2; ndx < 10; ++ndx)
+ {
+ if (!isHexChr(name[ndx]))
+ return false;
+ }
+
+ return true;
+}
+
+deUint32 getProgramIndexFromName (const std::string& name)
+{
+ DE_ASSERT(isProgramFileName(name));
+
+ deUint32 index = ~0u;
+ std::stringstream str;
+
+ str << std::hex << name.substr(2,10);
+ str >> index;
+
+ DE_ASSERT(getProgramFileName(index) == name);
+
+ return index;
}
string getIndexPath (const std::string& dirName)
return de::FilePath::join(dirName, "index.bin").getPath();
}
-void writeBinary (const std::string& dstDir, deUint32 index, const ProgramBinary& binary)
+void writeBinary (const ProgramBinary& binary, const std::string& dstPath)
{
- const de::FilePath fullPath = getProgramPath(dstDir, index);
+ const de::FilePath filePath(dstPath);
- if (!de::FilePath(fullPath.getDirName()).exists())
- de::createDirectoryAndParents(fullPath.getDirName().c_str());
+ if (!de::FilePath(filePath.getDirName()).exists())
+ de::createDirectoryAndParents(filePath.getDirName().c_str());
{
- std::ofstream out (fullPath.getPath(), std::ios_base::binary);
+ std::ofstream out (dstPath.c_str(), std::ios_base::binary);
if (!out.is_open() || !out.good())
- throw tcu::Exception("Failed to open " + string(fullPath.getPath()));
+ throw tcu::Exception("Failed to open " + dstPath);
out.write((const char*)binary.getBinary(), binary.getSize());
out.close();
}
}
+void writeBinary (const std::string& dstDir, deUint32 index, const ProgramBinary& binary)
+{
+ writeBinary(binary, getProgramPath(dstDir, index));
+}
+
+ProgramBinary* readBinary (const std::string& srcPath)
+{
+ std::ifstream in (srcPath.c_str(), std::ios::binary | std::ios::ate);
+ const size_t size = (size_t)in.tellg();
+
+ if (!in.is_open() || !in.good())
+ throw tcu::Exception("Failed to open " + srcPath);
+
+ if (size == 0)
+ throw tcu::Exception("Malformed binary, size = 0");
+
+ in.seekg(0, std::ios::beg);
+
+ {
+ std::vector<deUint8> bytes (size);
+
+ in.read((char*)&bytes[0], size);
+ DE_ASSERT(bytes[0] != 0);
+
+ return new ProgramBinary(vk::PROGRAM_FORMAT_SPIRV, bytes.size(), &bytes[0]);
+ }
+}
+
deUint32 binaryHash (const ProgramBinary* binary)
{
return deMemoryHash(binary->getBinary(), binary->getSize());
}
}
+void buildBinaryIndex (std::vector<BinaryIndexNode>* dst, size_t numEntries, const ProgramIdentifierIndex* entries)
+{
+ de::UniquePtr<SparseIndexNode> sparseIndex (new SparseIndexNode());
+
+ for (size_t ndx = 0; ndx < numEntries; ndx++)
+ {
+ const std::vector<deUint32> searchPath = getSearchPath(entries[ndx].id);
+ addToSparseIndex(sparseIndex.get(), &searchPath[0], searchPath.size(), entries[ndx].index);
+ }
+
+ normalizeSparseIndex(sparseIndex.get());
+ buildFinalIndex(dst, sparseIndex.get());
+}
+
} // anonymous
-// BinaryRegistryWriter
+// BinaryIndexHash
-DE_IMPLEMENT_POOL_HASH(BinaryHash, const ProgramBinary*, deUint32, binaryHash, binaryEqual);
+DE_IMPLEMENT_POOL_HASH(BinaryIndexHashImpl, const ProgramBinary*, deUint32, binaryHash, binaryEqual);
-BinaryRegistryWriter::BinaryRegistryWriter (const std::string& dstPath)
- : m_dstPath (dstPath)
- , m_binaryIndexMap (DE_NULL)
+BinaryIndexHash::BinaryIndexHash (void)
+ : m_hash(BinaryIndexHashImpl_create(m_memPool.getRawPool()))
{
- m_binaryIndexMap = BinaryHash_create(m_memPool.getRawPool());
+ if (!m_hash)
+ throw std::bad_alloc();
+}
- if (!m_binaryIndexMap)
+BinaryIndexHash::~BinaryIndexHash (void)
+{
+}
+
+deUint32* BinaryIndexHash::find (const ProgramBinary* binary) const
+{
+ return BinaryIndexHashImpl_find(m_hash, binary);
+}
+
+void BinaryIndexHash::insert (const ProgramBinary* binary, deUint32 index)
+{
+ if (!BinaryIndexHashImpl_insert(m_hash, binary, index))
throw std::bad_alloc();
}
+// BinaryRegistryWriter
+
+BinaryRegistryWriter::BinaryRegistryWriter (const std::string& dstPath)
+ : m_dstPath(dstPath)
+{
+ if (de::FilePath(dstPath).exists())
+ initFromPath(dstPath);
+}
+
BinaryRegistryWriter::~BinaryRegistryWriter (void)
{
- for (BinaryVector::const_iterator binaryIter = m_compactedBinaries.begin();
- binaryIter != m_compactedBinaries.end();
+ for (BinaryVector::const_iterator binaryIter = m_binaries.begin();
+ binaryIter != m_binaries.end();
++binaryIter)
- delete *binaryIter;
+ delete binaryIter->binary;
}
-void BinaryRegistryWriter::storeProgram (const ProgramIdentifier& id, const ProgramBinary& binary)
+void BinaryRegistryWriter::initFromPath (const std::string& srcPath)
{
- const deUint32* const indexPtr = BinaryHash_find(m_binaryIndexMap, &binary);
- deUint32 index = indexPtr ? *indexPtr : ~0u;
+ DE_ASSERT(m_binaries.empty());
- DE_ASSERT(binary.getFormat() == vk::PROGRAM_FORMAT_SPIRV);
-
- if (!indexPtr)
+ for (de::DirectoryIterator iter(srcPath); iter.hasItem(); iter.next())
{
- ProgramBinary* const binaryClone = new ProgramBinary(binary);
+ const de::FilePath path = iter.getItem();
+ const std::string baseName = path.getBaseName();
- try
+ if (isProgramFileName(baseName))
{
- index = (deUint32)m_compactedBinaries.size();
- m_compactedBinaries.push_back(binaryClone);
- }
- catch (...)
- {
- delete binaryClone;
- throw;
+ const deUint32 index = getProgramIndexFromName(baseName);
+ const de::UniquePtr<ProgramBinary> binary (readBinary(path.getPath()));
+
+ addBinary(index, *binary);
+ // \note referenceCount is left to 0 and will only be incremented
+ // if binary is reused (added via addProgram()).
}
+ }
+}
- writeBinary(m_dstPath, index, binary);
+void BinaryRegistryWriter::addProgram (const ProgramIdentifier& id, const ProgramBinary& binary)
+{
+ const deUint32* const indexPtr = findBinary(binary);
+ deUint32 index = indexPtr ? *indexPtr : ~0u;
- if (!BinaryHash_insert(m_binaryIndexMap, binaryClone, index))
- throw std::bad_alloc();
+ if (!indexPtr)
+ {
+ index = getNextSlot();
+ addBinary(index, binary);
}
- DE_ASSERT((size_t)index < m_compactedBinaries.size());
+ m_binaries[index].referenceCount += 1;
+ m_binaryIndices.push_back(ProgramIdentifierIndex(id, index));
+}
- m_binaryIndices.push_back(BinaryIndex(id, index));
+deUint32* BinaryRegistryWriter::findBinary (const ProgramBinary& binary) const
+{
+ return m_binaryHash.find(&binary);
}
-void BinaryRegistryWriter::writeIndex (void) const
+deUint32 BinaryRegistryWriter::getNextSlot (void) const
{
- const de::FilePath indexPath = getIndexPath(m_dstPath);
- std::vector<BinaryIndexNode> index;
+ const deUint32 index = (deUint32)m_binaries.size();
+
+ if ((size_t)index != m_binaries.size())
+ throw std::bad_alloc(); // Overflow
+
+ return index;
+}
+void BinaryRegistryWriter::addBinary (deUint32 index, const ProgramBinary& binary)
+{
+ DE_ASSERT(binary.getFormat() == vk::PROGRAM_FORMAT_SPIRV);
+ DE_ASSERT(findBinary(binary) == DE_NULL);
+
+ ProgramBinary* const binaryClone = new ProgramBinary(binary);
+
+ try
+ {
+ if (m_binaries.size() < (size_t)index+1)
+ m_binaries.resize(index+1);
+
+ DE_ASSERT(!m_binaries[index].binary);
+ DE_ASSERT(m_binaries[index].referenceCount == 0);
+
+ m_binaries[index].binary = binaryClone;
+ // \note referenceCount is not incremented here
+ }
+ catch (...)
+ {
+ delete binaryClone;
+ throw;
+ }
+
+ m_binaryHash.insert(binaryClone, index);
+}
+
+void BinaryRegistryWriter::write (void) const
+{
+ writeToPath(m_dstPath);
+}
+
+void BinaryRegistryWriter::writeToPath (const std::string& dstPath) const
+{
+ if (!de::FilePath(dstPath).exists())
+ de::createDirectoryAndParents(dstPath.c_str());
+
+ DE_ASSERT(m_binaries.size() <= 0xffffffffu);
+ for (size_t binaryNdx = 0; binaryNdx < m_binaries.size(); ++binaryNdx)
{
- de::UniquePtr<SparseIndexNode> sparseIndex (new SparseIndexNode());
+ const BinarySlot& slot = m_binaries[binaryNdx];
- for (size_t progNdx = 0; progNdx < m_binaryIndices.size(); progNdx++)
+ if (slot.referenceCount > 0)
{
- const std::vector<deUint32> searchPath = getSearchPath(m_binaryIndices[progNdx].id);
- addToSparseIndex(sparseIndex.get(), &searchPath[0], searchPath.size(), m_binaryIndices[progNdx].index);
+ DE_ASSERT(slot.binary);
+ writeBinary(dstPath, (deUint32)binaryNdx, *slot.binary);
+ }
+ else
+ {
+ // Delete stale binary if such exists
+ const std::string progPath = getProgramPath(dstPath, (deUint32)binaryNdx);
+
+ if (de::FilePath(progPath).exists())
+ deDeleteFile(progPath.c_str());
}
- normalizeSparseIndex(sparseIndex.get());
- buildFinalIndex(&index, sparseIndex.get());
}
- // Even in empty index there is always terminating node for the root group
- DE_ASSERT(!index.empty());
+ // Write index
+ {
+ const de::FilePath indexPath = getIndexPath(dstPath);
+ std::vector<BinaryIndexNode> index;
- if (!de::FilePath(indexPath.getDirName()).exists())
- de::createDirectoryAndParents(indexPath.getDirName().c_str());
+ buildBinaryIndex(&index, m_binaryIndices.size(), !m_binaryIndices.empty() ? &m_binaryIndices[0] : DE_NULL);
- {
- std::ofstream indexOut(indexPath.getPath(), std::ios_base::binary);
+ // Even in empty index there is always terminating node for the root group
+ DE_ASSERT(!index.empty());
+
+ if (!de::FilePath(indexPath.getDirName()).exists())
+ de::createDirectoryAndParents(indexPath.getDirName().c_str());
- if (!indexOut.is_open() || !indexOut.good())
- throw tcu::InternalError(string("Failed to open program binary index file ") + indexPath.getPath());
+ {
+ std::ofstream indexOut(indexPath.getPath(), std::ios_base::binary);
+
+ if (!indexOut.is_open() || !indexOut.good())
+ throw tcu::InternalError(string("Failed to open program binary index file ") + indexPath.getPath());
- indexOut.write((const char*)&index[0], index.size()*sizeof(BinaryIndexNode));
+ indexOut.write((const char*)&index[0], index.size()*sizeof(BinaryIndexNode));
+ }
}
}
typedef LazyResource<BinaryIndexNode> BinaryIndexAccess;
-DE_DECLARE_POOL_HASH(BinaryHash, const ProgramBinary*, deUint32);
-
class BinaryRegistryReader
{
public:
mutable BinaryIndexPtr m_binaryIndex;
};
+struct ProgramIdentifierIndex
+{
+ ProgramIdentifier id;
+ deUint32 index;
+
+ ProgramIdentifierIndex (const ProgramIdentifier& id_,
+ deUint32 index_)
+ : id (id_)
+ , index (index_)
+ {}
+};
+
+DE_DECLARE_POOL_HASH(BinaryIndexHashImpl, const ProgramBinary*, deUint32);
+
+class BinaryIndexHash
+{
+public:
+ BinaryIndexHash (void);
+ ~BinaryIndexHash (void);
+
+ deUint32* find (const ProgramBinary* binary) const;
+ void insert (const ProgramBinary* binary, deUint32 index);
+
+private:
+ BinaryIndexHash (const BinaryIndexHash&);
+ BinaryIndexHash& operator= (const BinaryIndexHash&);
+
+ de::MemPool m_memPool;
+ BinaryIndexHashImpl* const m_hash;
+};
+
class BinaryRegistryWriter
{
public:
BinaryRegistryWriter (const std::string& dstPath);
~BinaryRegistryWriter (void);
- void storeProgram (const ProgramIdentifier& id, const ProgramBinary& binary);
- void writeIndex (void) const;
+ void addProgram (const ProgramIdentifier& id, const ProgramBinary& binary);
+ void write (void) const;
private:
- struct BinaryIndex
+ void initFromPath (const std::string& srcPath);
+ void writeToPath (const std::string& dstPath) const;
+
+ deUint32* findBinary (const ProgramBinary& binary) const;
+ deUint32 getNextSlot (void) const;
+ void addBinary (deUint32 index, const ProgramBinary& binary);
+
+ struct BinarySlot
{
- ProgramIdentifier id;
- deUint32 index;
+ ProgramBinary* binary;
+ size_t referenceCount;
+
+ BinarySlot (ProgramBinary* binary_, size_t referenceCount_)
+ : binary (binary_)
+ , referenceCount(referenceCount_)
+ {}
- BinaryIndex (const ProgramIdentifier& id_,
- deUint32 index_)
- : id (id_)
- , index (index_)
+ BinarySlot (void)
+ : binary (DE_NULL)
+ , referenceCount(0)
{}
};
- typedef std::vector<ProgramBinary*> BinaryVector;
- typedef std::vector<BinaryIndex> BinaryIndexVector;
+ typedef std::vector<BinarySlot> BinaryVector;
+ typedef std::vector<ProgramIdentifierIndex> ProgIdIndexVector;
const std::string& m_dstPath;
- de::MemPool m_memPool;
- BinaryHash* m_binaryIndexMap; //!< ProgramBinary -> slot in m_compactedBinaries
- BinaryVector m_compactedBinaries;
- BinaryIndexVector m_binaryIndices; //!< ProgramIdentifier -> slot in m_compactedBinaries
+ ProgIdIndexVector m_binaryIndices; //!< ProgramIdentifier -> slot in m_binaries
+ BinaryIndexHash m_binaryHash; //!< ProgramBinary -> slot in m_binaries
+ BinaryVector m_binaries;
};
} // BinaryRegistryDetail
#include "vkGlslToSpirV.hpp"
#include "deArrayUtil.hpp"
-#include "deMutex.hpp"
#include "deSingleton.h"
#include "deMemory.h"
#include "deClock.h"
}
static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;
-static de::Mutex s_glslangLock;
void initGlslang (void*)
{
{
if (!program.sources[shaderType].empty())
{
- const de::ScopedLock compileLock (s_glslangLock);
const std::string& srcText = program.sources[shaderType][0];
const char* srcPtrs[] = { srcText.c_str() };
const int srcLengths[] = { (int)srcText.size() };
de::PoolArray<Program> programs (&programPool);
{
- // \todo [2016-09-30 pyry] Use main executor when glslang no longer requires global lock
- TaskExecutor buildGlslExecutor (1);
de::MemPool tmpPool;
de::PoolArray<BuildGlslTask> buildGlslTasks (&tmpPool);
de::PoolArray<BuildSpirVAsmTask> buildSpirvAsmTasks (&tmpPool);
{
programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName())));
buildGlslTasks.pushBack(BuildGlslTask(progIter.getProgram(), &programs.back()));
- buildGlslExecutor.submit(&buildGlslTasks.back());
+ executor.submit(&buildGlslTasks.back());
}
for (vk::SpirVAsmCollection::Iterator progIter = sourcePrograms.spirvAsmSources.begin();
}
// Need to wait until tasks completed before freeing task memory
- buildGlslExecutor.waitForComplete();
executor.waitForComplete();
}
for (de::PoolArray<Program>::iterator progIter = programs.begin(); progIter != programs.end(); ++progIter)
{
if (progIter->buildStatus == Program::STATUS_PASSED)
- registryWriter.storeProgram(progIter->id, *progIter->binary);
+ registryWriter.addProgram(progIter->id, *progIter->binary);
}
- registryWriter.writeIndex();
+ registryWriter.write();
}
{
namespace wayland
{
-enum
-{
- DEFAULT_WINDOW_WIDTH = 400,
- DEFAULT_WINDOW_HEIGHT = 300
-};
-
EventState::EventState (void)
: m_quit(false)
{
Display::Display (EventState& eventState, const char* name)
: m_eventState (eventState)
, m_display (DE_NULL)
+ , m_registry (DE_NULL)
+ , m_compositor (DE_NULL)
+ , m_shell (DE_NULL)
{
try
{
namespace wayland
{
+enum
+{
+ DEFAULT_WINDOW_WIDTH = 400,
+ DEFAULT_WINDOW_HEIGHT = 300
+};
+
class EventState
{
public:
void processEvents (void);
Display& getDisplay (void) { return m_display; }
+ void* getSurface (void) { return m_surface; }
void* getWindow (void) { return m_window; }
void getDimensions (int* width, int* height) const;
#include "gluPlatform.hpp"
#include "vkPlatform.hpp"
#include "tcuWayland.hpp"
+#include "tcuWaylandVulkanPlatform.hpp"
#include "tcuFunctionLibrary.hpp"
#include "deMemory.h"
}
};
-class VulkanLibrary : public vk::Library
-{
-public:
- VulkanLibrary (void)
- : m_library ("libvulkan.so.1")
- , m_driver (m_library)
- {
- }
-
- const vk::PlatformInterface& getPlatformInterface (void) const
- {
- return m_driver;
- }
-
-private:
- const tcu::DynamicFunctionLibrary m_library;
- const vk::PlatformDriver m_driver;
-};
-
-class WaylandVulkanPlatform : public vk::Platform
-{
-public:
- vk::Library* createLibrary (void) const
- {
- return new VulkanLibrary();
- }
-
- void describePlatform (std::ostream& dst) const
- {
- utsname sysInfo;
-
- deMemset(&sysInfo, 0, sizeof(sysInfo));
-
- if (uname(&sysInfo) != 0)
- throw std::runtime_error("uname() failed");
-
- dst << "OS: " << sysInfo.sysname << " " << sysInfo.release << " " << sysInfo.version << "\n";
- dst << "CPU: " << sysInfo.machine << "\n";
- }
-
- void getMemoryLimits (vk::PlatformMemoryLimits& limits) const
- {
- limits.totalSystemMemory = 256*1024*1024;
- limits.totalDeviceLocalMemory = 128*1024*1024;
- limits.deviceMemoryAllocationGranularity = 64*1024;
- limits.devicePageSize = 4096;
- limits.devicePageTableEntrySize = 8;
- limits.devicePageTableHierarchyLevels = 3;
- }
-};
-
class WaylandPlatform : public tcu::Platform
{
public:
WaylandPlatform::WaylandPlatform (void)
: m_eglPlatform (m_eventState)
+ , m_vkPlatform (m_eventState)
{
m_glPlatform.registerFactory(m_eglPlatform.createContextFactory());
}
--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group 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.
+ *
+ *//*!
+ * \file
+ * \brief Wayland Vulkan Platform.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuWaylandVulkanPlatform.hpp"
+#include "tcuWaylandPlatform.hpp"
+#include "vkWsiPlatform.hpp"
+#include "gluPlatform.hpp"
+#include "tcuWayland.hpp"
+#include "tcuFunctionLibrary.hpp"
+#include "deUniquePtr.hpp"
+#include "deMemory.h"
+
+#include <sys/utsname.h>
+
+using de::MovePtr;
+using de::UniquePtr;
+
+namespace tcu
+{
+namespace wayland
+{
+
+class VulkanWindowWayland : public vk::wsi::WaylandWindowInterface
+{
+public:
+ VulkanWindowWayland (MovePtr<wayland::Window> window)
+ : vk::wsi::WaylandWindowInterface (vk::pt::WaylandSurfacePtr(window->getSurface()))
+ , m_window (window)
+ {
+ }
+
+ void resize (const UVec2& newSize)
+ {
+ m_window->setDimensions((int)newSize.x(), (int)newSize.y());
+ }
+
+private:
+ UniquePtr<wayland::Window> m_window;
+};
+
+class VulkanDisplayWayland : public vk::wsi::WaylandDisplayInterface
+{
+public:
+ VulkanDisplayWayland (MovePtr<wayland::Display> display)
+ : vk::wsi::WaylandDisplayInterface (vk::pt::WaylandDisplayPtr(display->getDisplay()))
+ , m_display (display)
+ {
+ }
+
+ vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
+ {
+ const deUint32 height = !initialSize ? (deUint32)DEFAULT_WINDOW_HEIGHT : initialSize->y();
+ const deUint32 width = !initialSize ? (deUint32)DEFAULT_WINDOW_WIDTH : initialSize->x();
+ return new VulkanWindowWayland(MovePtr<wayland::Window>(new wayland::Window(*m_display, (int)width, (int)height)));
+ }
+
+private:
+ MovePtr<wayland::Display> m_display;
+};
+
+class VulkanLibrary : public vk::Library
+{
+public:
+ VulkanLibrary (void)
+ : m_library ("libvulkan.so.1")
+ , m_driver (m_library)
+ {
+ }
+
+ const vk::PlatformInterface& getPlatformInterface (void) const
+ {
+ return m_driver;
+ }
+
+private:
+ const DynamicFunctionLibrary m_library;
+ const vk::PlatformDriver m_driver;
+};
+
+WaylandVulkanPlatform::WaylandVulkanPlatform (EventState& eventState)
+ : m_eventState(eventState)
+{
+}
+
+vk::wsi::Display* WaylandVulkanPlatform::createWsiDisplay (vk::wsi::Type wsiType) const
+{
+ switch(wsiType)
+ {
+ case vk::wsi::TYPE_WAYLAND:
+ return new VulkanDisplayWayland(MovePtr<Display>(new Display(m_eventState, DE_NULL)));
+ break;
+ default:
+ TCU_THROW(NotSupportedError, "WSI type not supported");
+
+ };
+}
+
+vk::Library* WaylandVulkanPlatform::createLibrary (void) const
+{
+ return new VulkanLibrary();
+}
+
+void WaylandVulkanPlatform::describePlatform (std::ostream& dst) const
+{
+ utsname sysInfo;
+ deMemset(&sysInfo, 0, sizeof(sysInfo));
+
+ if (uname(&sysInfo) != 0)
+ throw std::runtime_error("uname() failed");
+
+ dst << "OS: " << sysInfo.sysname << " " << sysInfo.release << " " << sysInfo.version << "\n";
+ dst << "CPU: " << sysInfo.machine << "\n";
+}
+
+void WaylandVulkanPlatform::getMemoryLimits (vk::PlatformMemoryLimits& limits) const
+{
+ limits.totalSystemMemory = 256*1024*1024;
+ limits.totalDeviceLocalMemory = 128*1024*1024;
+ limits.deviceMemoryAllocationGranularity = 64*1024;
+ limits.devicePageSize = 4096;
+ limits.devicePageTableEntrySize = 8;
+ limits.devicePageTableHierarchyLevels = 3;
+}
+
+} // wayland
+} // tcu
+
--- /dev/null
+#ifndef _TCUWAYLANDVULKANPLATFORM_HPP
+#define _TCUWAYLANDVULKANPLATFORM_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright (c) 2016 The Khronos Group 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.
+ *
+ *//*!
+ * \file
+ * \brief Wayland Vulkan Platform.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkWsiPlatform.hpp"
+#include "vkPlatform.hpp"
+#include "tcuWayland.hpp"
+
+namespace tcu
+{
+namespace wayland
+{
+
+class WaylandVulkanPlatform : public vk::Platform
+{
+public:
+ WaylandVulkanPlatform (EventState& eventState);
+ vk::wsi::Display* createWsiDisplay (vk::wsi::Type wsiType) const;
+ vk::Library* createLibrary (void) const;
+ void describePlatform (std::ostream& dst) const;
+ void getMemoryLimits (vk::PlatformMemoryLimits& limits) const;
+
+private :
+ EventState& m_eventState;
+};
+
+
+} // wayland
+} // tcu
+
+#endif // _TCUWAYLANDVULKANPLATFORM_HPP
wayland/tcuWaylandPlatform.hpp
wayland/tcuWaylandEglPlatform.cpp
wayland/tcuWaylandEglPlatform.hpp
+ wayland/tcuWaylandVulkanPlatform.cpp
+ wayland/tcuWaylandVulkanPlatform.hpp
)