/*------------------------------------------------------------------------- * drawElements Quality Program EGL Module * --------------------------------------- * * Copyright 2014 The Android Open Source Project * * 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 EGL gles2 sharing threaded tests *//*--------------------------------------------------------------------*/ #include "teglGLES2SharingThreadedTests.hpp" #include "tcuTestLog.hpp" #include "tcuThreadUtil.hpp" #include "deRandom.hpp" #include "deThread.hpp" #include "deSharedPtr.hpp" #include "deMutex.hpp" #include "deSemaphore.hpp" #include "deStringUtil.hpp" #include "deClock.h" #include "deString.h" #include "deMemory.h" #include "deMath.h" #include "gluDefs.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "egluUtil.hpp" #include "eglwLibrary.hpp" #include "eglwEnums.hpp" #include <vector> #include <string> #include <memory> #include <sstream> using std::vector; using std::string; using de::SharedPtr; using namespace glw; using namespace eglw; namespace deqp { namespace egl { namespace GLES2ThreadTest { class Texture; class Buffer; class Shader; class Program; class GLES2ResourceManager { public: SharedPtr<Texture> popTexture (int index); const SharedPtr<Texture> getTexture (int index) const { return m_textures[index]; } void addTexture (SharedPtr<Texture> texture) { m_textures.push_back(texture); } int getTextureCount (void) const { return (int)m_textures.size(); } SharedPtr<Buffer> popBuffer (int index); const SharedPtr<Buffer> getBuffer (int index) const { return m_buffers[index]; } void addBuffer (SharedPtr<Buffer> buffer) { m_buffers.push_back(buffer); } int getBufferCount (void) const { return (int)m_buffers.size(); } SharedPtr<Shader> popShader (int index); const SharedPtr<Shader> getShader (int index) const { return m_shaders[index]; } void addShader (SharedPtr<Shader> shader) { m_shaders.push_back(shader); } int getShaderCount (void) const { return (int)m_shaders.size(); } SharedPtr<Program> popProgram (int index); const SharedPtr<Program> getProgram (int index) const { return m_programs[index]; } void addProgram (SharedPtr<Program> program) { m_programs.push_back(program); } int getProgramCount (void) const { return (int)m_programs.size(); } private: std::vector<SharedPtr<Texture> > m_textures; std::vector<SharedPtr<Buffer> > m_buffers; std::vector<SharedPtr<Shader> > m_shaders; std::vector<SharedPtr<Program> > m_programs; }; SharedPtr<Texture> GLES2ResourceManager::popTexture (int index) { SharedPtr<Texture> texture = m_textures[index]; m_textures.erase(m_textures.begin() + index); return texture; } SharedPtr<Buffer> GLES2ResourceManager::popBuffer (int index) { SharedPtr<Buffer> buffer = m_buffers[index]; m_buffers.erase(m_buffers.begin() + index); return buffer; } SharedPtr<Shader> GLES2ResourceManager::popShader (int index) { SharedPtr<Shader> shader = m_shaders[index]; m_shaders.erase(m_shaders.begin() + index); return shader; } SharedPtr<Program> GLES2ResourceManager::popProgram (int index) { SharedPtr<Program> program = m_programs[index]; m_programs.erase(m_programs.begin() + index); return program; } class GLES2Context : public tcu::ThreadUtil::Object { public: GLES2Context (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<GLES2ResourceManager> resourceManager); ~GLES2Context (void); // Call generation time attributes SharedPtr<GLES2ResourceManager> resourceManager; // Run time attributes EGLDisplay display; EGLContext context; struct { glEGLImageTargetTexture2DOESFunc imageTargetTexture2D; } glExtensions; private: GLES2Context (const GLES2Context&); GLES2Context& operator= (const GLES2Context&); }; GLES2Context::GLES2Context (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<GLES2ResourceManager> resourceManager_) : tcu::ThreadUtil::Object ("Context", event) , resourceManager (resourceManager_) , display (EGL_NO_DISPLAY) , context (EGL_NO_CONTEXT) { glExtensions.imageTargetTexture2D = DE_NULL; } GLES2Context::~GLES2Context (void) { } class Surface : public tcu::ThreadUtil::Object { public: Surface (SharedPtr<tcu::ThreadUtil::Event> event); ~Surface (void); // Run time attributes EGLSurface surface; private: Surface (const Surface&); Surface& operator= (const Surface&); }; Surface::Surface (SharedPtr<tcu::ThreadUtil::Event> event) : tcu::ThreadUtil::Object ("Surface", event) , surface (EGL_NO_SURFACE) { } Surface::~Surface (void) { } // EGL thread with thread specifig state class EGLThread : public tcu::ThreadUtil::Thread { public: EGLThread (const Library& egl_, const glw::Functions& gl_, int seed); ~EGLThread (void); virtual void deinit (void); const Library& egl; const glw::Functions& gl; // Generation time attributes SharedPtr<GLES2Context> context; SharedPtr<Surface> surface; // Runtime attributes SharedPtr<GLES2Context> runtimeContext; EGLSurface eglSurface; private: }; EGLThread::EGLThread (const Library& egl_, const glw::Functions& gl_, int seed) : tcu::ThreadUtil::Thread (seed) , egl (egl_) , gl (gl_) , eglSurface (EGL_NO_SURFACE) { } void EGLThread::deinit (void) { if (runtimeContext) { if (runtimeContext->context != EGL_NO_CONTEXT) egl.makeCurrent(runtimeContext->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); egl.destroyContext(runtimeContext->display, runtimeContext->context); runtimeContext->context = EGL_NO_CONTEXT; egl.destroySurface(runtimeContext->display, eglSurface); eglSurface = EGL_NO_SURFACE; } egl.releaseThread(); } EGLThread::~EGLThread (void) { EGLThread::deinit(); } class FenceSync { public: FenceSync (void); ~FenceSync (void); void init (EGLThread& thread, bool serverSync); bool waitReady (EGLThread& thread); void addWaiter (void); private: EGLDisplay m_display; EGLSyncKHR m_sync; de::Mutex m_lock; int m_waiterCount; bool m_serverSync; }; FenceSync::FenceSync (void) : m_display (EGL_NO_DISPLAY) , m_sync (NULL) , m_waiterCount (0) , m_serverSync (false) { } FenceSync::~FenceSync (void) { } void FenceSync::addWaiter (void) { m_lock.lock(); m_waiterCount++; m_lock.unlock(); } void FenceSync::init (EGLThread& thread, bool serverSync) { m_display = thread.runtimeContext->display; m_serverSync = serverSync; // Use sync only if somebody will actualy depend on it m_lock.lock(); if (m_waiterCount > 0) { thread.newMessage() << "Begin -- eglCreateSyncKHR(" << ((size_t)m_display) << ", EGL_SYNC_FENCE_KHR, DE_NULL)" << tcu::ThreadUtil::Message::End; m_sync = thread.egl.createSyncKHR(m_display, EGL_SYNC_FENCE_KHR, DE_NULL); thread.newMessage() << "End -- " << ((size_t)m_sync) << " = eglCreateSyncKHR()" << tcu::ThreadUtil::Message::End; TCU_CHECK(m_sync); } m_lock.unlock(); } bool FenceSync::waitReady (EGLThread& thread) { bool ok = true; if (m_serverSync) { thread.newMessage() << "Begin -- eglWaitSyncKHR(" << ((size_t)m_display) << ", " << ((size_t)m_sync) << ", 0)" << tcu::ThreadUtil::Message::End; EGLint result = thread.egl.waitSyncKHR(m_display, m_sync, 0); thread.newMessage() << "End -- " << result << " = eglWaitSyncKHR()" << tcu::ThreadUtil::Message::End; ok = result == EGL_TRUE; } else { thread.newMessage() << "Begin -- eglClientWaitSyncKHR(" << ((size_t)m_display) << ", " << ((size_t)m_sync) << ", EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000 000 000)" << tcu::ThreadUtil::Message::End; EGLint result = thread.egl.clientWaitSyncKHR(m_display, m_sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000000000); thread.newMessage() << "End -- " << result << " = eglClientWaitSyncKHR()" << tcu::ThreadUtil::Message::End; ok = result == EGL_CONDITION_SATISFIED_KHR; } m_lock.lock(); m_waiterCount--; DE_ASSERT(m_waiterCount >= 0); if (m_waiterCount == 0) { // \note [mika] This is no longer deterministic and eglDestroySyncKHR might happen in different places and in different threads thread.newMessage() << "Begin -- eglDestroySyncKHR(" << ((size_t)m_display) << ", " << ((size_t)m_sync) << ")" << tcu::ThreadUtil::Message::End; EGLint destroyResult = thread.egl.destroySyncKHR(m_display, m_sync); thread.newMessage() << "End -- " << destroyResult << " = eglDestroySyncKHR()" << tcu::ThreadUtil::Message::End; m_sync = DE_NULL; } m_lock.unlock(); return ok; } class Object : public tcu::ThreadUtil::Object { public: Object (const char* type, SharedPtr<tcu::ThreadUtil::Event> e, SharedPtr<FenceSync> sync); ~Object (void); void readGL (SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps); void modifyGL (SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps); private: SharedPtr<FenceSync> m_modifySync; vector<SharedPtr<FenceSync> > m_readSyncs; }; Object::Object (const char* type, SharedPtr<tcu::ThreadUtil::Event> e, SharedPtr<FenceSync> sync) : tcu::ThreadUtil::Object (type, e) , m_modifySync (sync) { } Object::~Object (void) { } void Object::readGL (SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps) { if (m_modifySync) m_modifySync->addWaiter(); // Make call depend on last modifying call deps.push_back(m_modifySync); // Add read dependency m_readSyncs.push_back(sync); } void Object::modifyGL (SharedPtr<FenceSync> sync, std::vector<SharedPtr<FenceSync> >& deps) { // Make call depend on all reads for (int readNdx = 0; readNdx < (int)m_readSyncs.size(); readNdx++) { if (m_readSyncs[readNdx]) m_readSyncs[readNdx]->addWaiter(); deps.push_back(m_readSyncs[readNdx]); } if (m_modifySync) m_modifySync->addWaiter(); deps.push_back(m_modifySync); // Update last modifying call m_modifySync = sync; // Clear read dependencies of last "version" of this object m_readSyncs.clear(); } class Operation : public tcu::ThreadUtil::Operation { public: Operation (const char* name, bool useSync, bool serverSync); virtual ~Operation (void); SharedPtr<FenceSync> getSync (void) { return m_sync; } void readGLObject (SharedPtr<Object> object); void modifyGLObject (SharedPtr<Object> object); virtual void execute (tcu::ThreadUtil::Thread& thread); private: bool m_useSync; bool m_serverSync; std::vector<SharedPtr<FenceSync> > m_syncDeps; SharedPtr<FenceSync> m_sync; }; Operation::Operation (const char* name, bool useSync, bool serverSync) : tcu::ThreadUtil::Operation (name) , m_useSync (useSync) , m_serverSync (serverSync) , m_sync (useSync ? SharedPtr<FenceSync>(new FenceSync()) : SharedPtr<FenceSync>()) { } Operation::~Operation (void) { } void Operation::readGLObject (SharedPtr<Object> object) { object->read(m_event, m_deps); object->readGL(m_sync, m_syncDeps); } void Operation::modifyGLObject (SharedPtr<Object> object) { object->modify(m_event, m_deps); object->modifyGL(m_sync, m_syncDeps); } void Operation::execute (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); bool success = true; // Wait for dependencies and check that they succeeded for (int depNdx = 0; depNdx < (int)m_deps.size(); depNdx++) { if (!m_deps[depNdx]->waitReady()) success = false; } // Try execute operation if (success) { try { if (m_useSync) { for (int depNdx = 0; depNdx < (int)m_syncDeps.size(); depNdx++) { EGLThread* eglThread = dynamic_cast<EGLThread*>(&thread); DE_ASSERT(eglThread); if (m_syncDeps[depNdx]->waitReady(*eglThread) != tcu::ThreadUtil::Event::RESULT_OK) { success = false; break; } } } if (success) { exec(thread); if (m_useSync) { EGLThread* eglThread = dynamic_cast<EGLThread*>(&thread); DE_ASSERT(eglThread); m_sync->init(*eglThread, m_serverSync); thread.newMessage() << "Begin -- glFlush()" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, flush()); thread.newMessage() << "End -- glFlush()" << tcu::ThreadUtil::Message::End; } else { thread.newMessage() << "Begin -- glFinish()" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, finish()); thread.newMessage() << "End -- glFinish()" << tcu::ThreadUtil::Message::End; } } } catch (...) { // Got exception event failed m_event->setResult(tcu::ThreadUtil::Event::RESULT_FAILED); throw; } } if (success) m_event->setResult(tcu::ThreadUtil::Event::RESULT_OK); else m_event->setResult(tcu::ThreadUtil::Event::RESULT_FAILED); m_deps.clear(); m_event = SharedPtr<tcu::ThreadUtil::Event>(); m_syncDeps.clear(); m_sync = SharedPtr<FenceSync>(); } class EGLImage : public Object { public: EGLImage (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync); virtual ~EGLImage (void) {} EGLImageKHR image; }; // EGLResource manager class EGLResourceManager { public: void addContext (SharedPtr<GLES2Context> context) { m_contexts.push_back(context); } void addSurface (SharedPtr<Surface> surface) { m_surfaces.push_back(surface); } void addImage (SharedPtr<EGLImage> image) { m_images.push_back(image); } SharedPtr<Surface> popSurface (int index); SharedPtr<GLES2Context> popContext (int index); SharedPtr<EGLImage> popImage (int index); int getContextCount (void) const { return (int)m_contexts.size(); } int getSurfaceCount (void) const { return (int)m_surfaces.size(); } int getImageCount (void) const { return (int)m_images.size(); } private: std::vector<SharedPtr<GLES2Context> > m_contexts; std::vector<SharedPtr<Surface> > m_surfaces; std::vector<SharedPtr<EGLImage> > m_images; }; SharedPtr<Surface> EGLResourceManager::popSurface (int index) { SharedPtr<Surface> surface = m_surfaces[index]; m_surfaces.erase(m_surfaces.begin() + index); return surface; } SharedPtr<GLES2Context> EGLResourceManager::popContext (int index) { SharedPtr<GLES2Context> context = m_contexts[index]; m_contexts.erase(m_contexts.begin() + index); return context; } SharedPtr<EGLImage> EGLResourceManager::popImage (int index) { SharedPtr<EGLImage> image = m_images[index]; m_images.erase(m_images.begin() + index); return image; } class CreateContext : public tcu::ThreadUtil::Operation { public: CreateContext (EGLDisplay display, EGLConfig config, SharedPtr<GLES2Context> shared, SharedPtr<GLES2Context>& context); void exec (tcu::ThreadUtil::Thread& thread); private: EGLDisplay m_display; EGLConfig m_config; SharedPtr<GLES2Context> m_shared; SharedPtr<GLES2Context> m_context; }; CreateContext::CreateContext (EGLDisplay display, EGLConfig config, SharedPtr<GLES2Context> shared, SharedPtr<GLES2Context>& context) : tcu::ThreadUtil::Operation ("CreateContext") , m_display (display) , m_config (config) , m_shared (shared) { if (shared) modifyObject(SharedPtr<tcu::ThreadUtil::Object>(shared)); context = SharedPtr<GLES2Context>(new GLES2Context(getEvent(), (shared ? shared->resourceManager : SharedPtr<GLES2ResourceManager>(new GLES2ResourceManager)))); m_context = context; } void CreateContext::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); m_context->display = m_display; const EGLint attriblist[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; thread.newMessage() << "Begin -- eglBindAPI(EGL_OPENGL_ES_API)" << tcu::ThreadUtil::Message::End; EGLU_CHECK_CALL(thread.egl, bindAPI(EGL_OPENGL_ES_API)); thread.newMessage() << "End -- eglBindAPI()" << tcu::ThreadUtil::Message::End; if (m_shared) { DE_ASSERT(m_shared->context != EGL_NO_CONTEXT); DE_ASSERT(m_shared->display != EGL_NO_DISPLAY); DE_ASSERT(m_shared->display == m_display); thread.newMessage() << "Begin -- eglCreateContext(" << m_display << ", " << m_config << ", " << m_shared->context << ", { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE })" << tcu::ThreadUtil::Message::End; m_context->context = thread.egl.createContext(m_display, m_config, m_shared->context, attriblist); thread.newMessage() << "End -- " << m_context->context << " = eglCreateContext()" << tcu::ThreadUtil::Message::End; } else { thread.newMessage() << "Begin -- eglCreateContext(" << m_display << ", " << m_config << ", EGL_NO_CONTEXT, { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE })" << tcu::ThreadUtil::Message::End; m_context->context = thread.egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attriblist); thread.newMessage() << "End -- " << m_context->context << " = eglCreateContext()" << tcu::ThreadUtil::Message::End; } EGLU_CHECK_MSG(thread.egl, "Failed to create GLES2 context"); TCU_CHECK(m_context->context != EGL_NO_CONTEXT); } class DestroyContext : public tcu::ThreadUtil::Operation { public: DestroyContext (SharedPtr<GLES2Context> contex); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<GLES2Context> m_context; }; DestroyContext::DestroyContext (SharedPtr<GLES2Context> contex) : tcu::ThreadUtil::Operation ("DestroyContext") , m_context (contex) { modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_context)); } void DestroyContext::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- eglDestroyContext(" << m_context->display << ", " << m_context->context << ")" << tcu::ThreadUtil::Message::End; EGLU_CHECK_CALL(thread.egl, destroyContext(m_context->display, m_context->context)); thread.newMessage() << "End -- eglDestroyContext()" << tcu::ThreadUtil::Message::End; m_context->display = EGL_NO_DISPLAY; m_context->context = EGL_NO_CONTEXT; } class MakeCurrent : public tcu::ThreadUtil::Operation { public: MakeCurrent (EGLThread& thread, EGLDisplay display, SharedPtr<Surface> surface, SharedPtr<GLES2Context> context); void exec (tcu::ThreadUtil::Thread& thread); private: EGLDisplay m_display; SharedPtr<Surface> m_surface; SharedPtr<GLES2Context> m_context; }; MakeCurrent::MakeCurrent (EGLThread& thread, EGLDisplay display, SharedPtr<Surface> surface, SharedPtr<GLES2Context> context) : tcu::ThreadUtil::Operation ("MakeCurrent") , m_display (display) , m_surface (surface) , m_context (context) { if (m_context) modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_context)); if (m_surface) modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_surface)); // Release old contexts if (thread.context) { modifyObject(SharedPtr<tcu::ThreadUtil::Object>(thread.context)); } // Release old surface if (thread.surface) { modifyObject(SharedPtr<tcu::ThreadUtil::Object>(thread.surface)); } thread.context = m_context; thread.surface = m_surface; } void MakeCurrent::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); if (m_context) { thread.eglSurface = m_surface->surface; thread.runtimeContext = m_context; DE_ASSERT(m_surface); thread.newMessage() << "Begin -- eglMakeCurrent(" << m_display << ", " << m_surface->surface << ", " << m_surface->surface << ", " << m_context->context << ")" << tcu::ThreadUtil::Message::End; EGLU_CHECK_CALL(thread.egl, makeCurrent(m_display, m_surface->surface, m_surface->surface, m_context->context)); thread.newMessage() << "End -- eglMakeCurrent()" << tcu::ThreadUtil::Message::End; } else { thread.runtimeContext = m_context; thread.newMessage() << "Begin -- eglMakeCurrent(" << m_display << ", EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)" << tcu::ThreadUtil::Message::End; EGLU_CHECK_CALL(thread.egl, makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); thread.newMessage() << "End -- eglMakeCurrent()" << tcu::ThreadUtil::Message::End; } } class InitGLExtension : public tcu::ThreadUtil::Operation { public: InitGLExtension (const char* extension); void exec (tcu::ThreadUtil::Thread& thread); private: std::string m_extension; }; InitGLExtension::InitGLExtension (const char* extension) : tcu::ThreadUtil::Operation ("InitGLExtension") , m_extension (extension) { } void InitGLExtension::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); // Check extensions bool found = false; thread.newMessage() << "Begin -- glGetString(GL_EXTENSIONS)" << tcu::ThreadUtil::Message::End; std::string extensions = (const char*)thread.gl.getString(GL_EXTENSIONS); thread.newMessage() << "End -- glGetString()" << tcu::ThreadUtil::Message::End; std::string::size_type pos = extensions.find(" "); do { std::string extension; if (pos != std::string::npos) { extension = extensions.substr(0, pos); extensions = extensions.substr(pos+1); } else { extension = extensions; extensions = ""; } if (extension == m_extension) { found = true; break; } pos = extensions.find(" "); } while (pos != std::string::npos); if (!found) throw tcu::NotSupportedError((m_extension + " not supported").c_str(), "", __FILE__, __LINE__); // Query function pointers if (m_extension == "GL_OES_EGL_image") { thread.newMessage() << "Begin -- eglGetProcAddress(\"glEGLImageTargetTexture2DOES\")" << tcu::ThreadUtil::Message::End; thread.runtimeContext->glExtensions.imageTargetTexture2D = (glEGLImageTargetTexture2DOESFunc)thread.egl.getProcAddress("glEGLImageTargetTexture2DOES"); thread.newMessage() << "End -- " << ((void*)thread.runtimeContext->glExtensions.imageTargetTexture2D) << " = eglGetProcAddress()"<< tcu::ThreadUtil::Message::End; } } class CreatePBufferSurface : public tcu::ThreadUtil::Operation { public: CreatePBufferSurface (EGLDisplay display, EGLConfig config, EGLint width, EGLint height, SharedPtr<Surface>& surface); void exec (tcu::ThreadUtil::Thread& thread); private: EGLDisplay m_display; EGLConfig m_config; EGLint m_width; EGLint m_height; SharedPtr<Surface> m_surface; }; CreatePBufferSurface::CreatePBufferSurface (EGLDisplay display, EGLConfig config, EGLint width, EGLint height, SharedPtr<Surface>& surface) : tcu::ThreadUtil::Operation ("CreatePBufferSurface") , m_display (display) , m_config (config) , m_width (width) , m_height (height) { surface = SharedPtr<Surface>(new Surface(getEvent())); m_surface = surface; } void CreatePBufferSurface::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); const EGLint attriblist[] = { EGL_WIDTH, m_width, EGL_HEIGHT, m_height, EGL_NONE }; thread.newMessage() << "Begin -- eglCreatePbufferSurface(" << m_display << ", " << m_config << ", { EGL_WIDTH, " << m_width << ", EGL_HEIGHT, " << m_height << ", EGL_NONE })" << tcu::ThreadUtil::Message::End; m_surface->surface = thread.egl.createPbufferSurface(m_display, m_config, attriblist); thread.newMessage() << "End -- " << m_surface->surface << "= eglCreatePbufferSurface()" << tcu::ThreadUtil::Message::End; EGLU_CHECK_MSG(thread.egl, "eglCreatePbufferSurface()"); } class DestroySurface : public tcu::ThreadUtil::Operation { public: DestroySurface (EGLDisplay display, SharedPtr<Surface> surface); void exec (tcu::ThreadUtil::Thread& thread); private: EGLDisplay m_display; SharedPtr<Surface> m_surface; }; DestroySurface::DestroySurface (EGLDisplay display, SharedPtr<Surface> surface) : tcu::ThreadUtil::Operation ("DestroySurface") , m_display (display) , m_surface (surface) { modifyObject(SharedPtr<tcu::ThreadUtil::Object>(m_surface)); } void DestroySurface::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- eglDestroySurface(" << m_display << ", " << m_surface->surface << ")" << tcu::ThreadUtil::Message::End; EGLU_CHECK_CALL(thread.egl, destroySurface(m_display, m_surface->surface)); thread.newMessage() << "End -- eglDestroySurface()" << tcu::ThreadUtil::Message::End; } EGLImage::EGLImage (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync) : Object ("EGLImage", event, sync) , image (EGL_NO_IMAGE_KHR) { } class Texture : public Object { public: Texture (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync); // Runtime parameters GLuint texture; // Call generation time parameters bool isDefined; SharedPtr<EGLImage> sourceImage; }; Texture::Texture (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync) : Object ("Texture", event, sync) , texture (0) , isDefined (false) { } class CreateTexture : public Operation { public: CreateTexture (SharedPtr<Texture>& texture, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; }; CreateTexture::CreateTexture (SharedPtr<Texture>& texture, bool useSync, bool serverSync) : Operation ("CreateTexture", useSync, serverSync) { texture = SharedPtr<Texture>(new Texture(getEvent(), getSync())); m_texture = texture; } void CreateTexture::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint tex = 0; thread.newMessage() << "Begin -- glGenTextures(1, { 0 })" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, genTextures(1, &tex)); thread.newMessage() << "End -- glGenTextures(1, { " << tex << " })" << tcu::ThreadUtil::Message::End; m_texture->texture = tex; } class DeleteTexture : public Operation { public: DeleteTexture (SharedPtr<Texture> texture, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; }; DeleteTexture::DeleteTexture (SharedPtr<Texture> texture, bool useSync, bool serverSync) : Operation ("DeleteTexture", useSync, serverSync) , m_texture (texture) { modifyGLObject(SharedPtr<Object>(m_texture)); } void DeleteTexture::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint tex = m_texture->texture; thread.newMessage() << "Begin -- glDeleteTextures(1, { " << tex << " })" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, deleteTextures(1, &tex)); thread.newMessage() << "End -- glDeleteTextures()" << tcu::ThreadUtil::Message::End; m_texture->texture = 0; } class TexImage2D : public Operation { public: TexImage2D (SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; GLint m_level; GLint m_internalFormat; GLsizei m_width; GLsizei m_height; GLenum m_format; GLenum m_type; }; TexImage2D::TexImage2D (SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync) : Operation ("TexImage2D", useSync, serverSync) , m_texture (texture) , m_level (level) , m_internalFormat (internalFormat) , m_width (width) , m_height (height) , m_format (format) , m_type (type) { modifyGLObject(SharedPtr<Object>(m_texture)); m_texture->isDefined = true; // Orphang texture texture->sourceImage = SharedPtr<EGLImage>(); } void TexImage2D::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); void* dummyData = thread.getDummyData(m_width*m_height*4); thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glTexImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_internalFormat << ", " << m_width << ", " << m_height << ", 0, " << m_format << ", " << m_type << ", data)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, texImage2D(GL_TEXTURE_2D, m_level, m_internalFormat, m_width, m_height, 0, m_format, m_type, dummyData)); thread.newMessage() << "End -- glTexImage2D()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; } class TexSubImage2D : public Operation { public: TexSubImage2D (SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; GLint m_level; GLint m_xoffset; GLint m_yoffset; GLsizei m_width; GLsizei m_height; GLenum m_format; GLenum m_type; }; TexSubImage2D::TexSubImage2D (SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, bool useSync, bool serverSync) : Operation ("TexSubImage2D", useSync, serverSync) , m_texture (texture) , m_level (level) , m_xoffset (xoffset) , m_yoffset (yoffset) , m_width (width) , m_height (height) , m_format (format) , m_type (type) { modifyGLObject(SharedPtr<Object>(m_texture)); if (m_texture->sourceImage) modifyGLObject(SharedPtr<Object>(m_texture->sourceImage)); } void TexSubImage2D::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); void* dummyData = thread.getDummyData(m_width*m_height*4); thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glTexSubImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_xoffset << ", " << m_yoffset << ", " << m_width << ", " << m_height << ", 0, " << m_format << ", " << m_type << ", <data>)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, texSubImage2D(GL_TEXTURE_2D, m_level, m_xoffset, m_yoffset, m_width, m_height, m_format, m_type, dummyData)); thread.newMessage() << "End -- glSubTexImage2D()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; } class CopyTexImage2D : public Operation { public: CopyTexImage2D (SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; GLint m_level; GLint m_internalFormat; GLint m_x; GLint m_y; GLsizei m_width; GLsizei m_height; GLint m_border; }; CopyTexImage2D::CopyTexImage2D (SharedPtr<Texture> texture, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border, bool useSync, bool serverSync) : Operation ("CopyTexImage2D", useSync, serverSync) , m_texture (texture) , m_level (level) , m_internalFormat (internalFormat) , m_x (x) , m_y (y) , m_width (width) , m_height (height) , m_border (border) { modifyGLObject(SharedPtr<Object>(m_texture)); texture->isDefined = true; // Orphang texture texture->sourceImage = SharedPtr<EGLImage>(); } void CopyTexImage2D::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glCopyTexImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_internalFormat << ", " << m_x << ", " << m_y << ", " << m_width << ", " << m_height << ", " << m_border << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, copyTexImage2D(GL_TEXTURE_2D, m_level, m_internalFormat, m_x, m_y, m_width, m_height, m_border)); thread.newMessage() << "End -- glCopyTexImage2D()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; } class CopyTexSubImage2D : public Operation { public: CopyTexSubImage2D (SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; GLint m_level; GLint m_xoffset; GLint m_yoffset; GLint m_x; GLint m_y; GLsizei m_width; GLsizei m_height; }; CopyTexSubImage2D::CopyTexSubImage2D (SharedPtr<Texture> texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, bool useSync, bool serverSync) : Operation ("CopyTexSubImage2D", useSync, serverSync) , m_texture (texture) , m_level (level) , m_xoffset (xoffset) , m_yoffset (yoffset) , m_x (x) , m_y (y) , m_width (width) , m_height (height) { modifyGLObject(SharedPtr<Object>(m_texture)); if (m_texture->sourceImage) modifyGLObject(SharedPtr<Object>(m_texture->sourceImage)); } void CopyTexSubImage2D::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glCopyTexSubImage2D(GL_TEXTURE_2D, " << m_level << ", " << m_xoffset << ", " << m_yoffset << ", " << m_x << ", " << m_y << ", " << m_width << ", " << m_height << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, copyTexSubImage2D(GL_TEXTURE_2D, m_level, m_xoffset, m_yoffset, m_x, m_y, m_width, m_height)); thread.newMessage() << "End -- glCopyTexSubImage2D()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; } class Buffer : public Object { public: Buffer (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync); // Runtime attributes GLuint buffer; GLsizeiptr size; // Call generation time parameters bool isDefined; }; Buffer::Buffer (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync) : Object ("Buffer", event, sync) , buffer (0) , size (0) , isDefined (false) { } class CreateBuffer : public Operation { public: CreateBuffer (SharedPtr<Buffer>& buffer, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Buffer> m_buffer; }; CreateBuffer::CreateBuffer (SharedPtr<Buffer>& buffer, bool useSync, bool serverSync) : Operation ("CreateBuffer", useSync, serverSync) { buffer = SharedPtr<Buffer>(new Buffer(getEvent(), getSync())); m_buffer = buffer; } void CreateBuffer::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint buffer = 0; thread.newMessage() << "Begin -- glGenBuffers(1, { 0 })" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, genBuffers(1, &buffer)); thread.newMessage() << "End -- glGenBuffers(1, { " << buffer << " })" << tcu::ThreadUtil::Message::End; m_buffer->buffer = buffer; } class DeleteBuffer : public Operation { public: DeleteBuffer (SharedPtr<Buffer> buffer, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Buffer> m_buffer; }; DeleteBuffer::DeleteBuffer (SharedPtr<Buffer> buffer, bool useSync, bool serverSync) : Operation ("DeleteBuffer", useSync, serverSync) , m_buffer (buffer) { modifyGLObject(SharedPtr<Object>(m_buffer)); } void DeleteBuffer::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint buffer = m_buffer->buffer; thread.newMessage() << "Begin -- glDeleteBuffers(1, { " << buffer << " })" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, deleteBuffers(1, &buffer)); thread.newMessage() << "End -- glDeleteBuffers()" << tcu::ThreadUtil::Message::End; m_buffer->buffer = 0; } class BufferData : public Operation { public: BufferData (SharedPtr<Buffer> buffer, GLenum target, GLsizeiptr size, GLenum usage, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Buffer> m_buffer; GLenum m_target; GLsizeiptr m_size; GLenum m_usage; }; BufferData::BufferData (SharedPtr<Buffer> buffer, GLenum target, GLsizeiptr size, GLenum usage, bool useSync, bool serverSync) : Operation ("BufferData", useSync, serverSync) , m_buffer (buffer) , m_target (target) , m_size (size) , m_usage (usage) { modifyGLObject(SharedPtr<Object>(m_buffer)); buffer->isDefined = true; buffer->size = size; } void BufferData::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); void* dummyData = thread.getDummyData(m_size); thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", " << m_buffer->buffer << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, m_buffer->buffer)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBufferData(" << m_target << ", " << m_size << ", <DATA>, " << m_usage << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bufferData(m_target, m_size, dummyData, m_usage)); thread.newMessage() << "End -- glBufferData()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, 0)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; } class BufferSubData : public Operation { public: BufferSubData (SharedPtr<Buffer> buffer, GLenum target, GLintptr offset, GLsizeiptr size, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Buffer> m_buffer; GLenum m_target; GLintptr m_offset; GLsizeiptr m_size; }; BufferSubData::BufferSubData (SharedPtr<Buffer> buffer, GLenum target, GLintptr offset, GLsizeiptr size, bool useSync, bool serverSync) : Operation ("BufferSubData", useSync, serverSync) , m_buffer (buffer) , m_target (target) , m_offset (offset) , m_size (size) { modifyGLObject(SharedPtr<Object>(m_buffer)); } void BufferSubData::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); void* dummyData = thread.getDummyData(m_size); thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", " << m_buffer->buffer << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, m_buffer->buffer)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBufferSubData(" << m_target << ", " << m_offset << ", " << m_size << ", <DATA>)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bufferSubData(m_target, m_offset, m_size, dummyData)); thread.newMessage() << "End -- glBufferSubData()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindBuffer(" << m_target << ", 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(m_target, 0)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; } class Shader : public Object { public: Shader (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync); GLuint shader; GLenum type; bool isDefined; bool compiled; }; Shader::Shader (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync) : Object ("Shader", event, sync) , shader (0) , type (GL_NONE) , isDefined (false) , compiled (false) { } class CreateShader : public Operation { public: CreateShader (GLenum type, SharedPtr<Shader>& shader, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Shader> m_shader; GLenum m_type; }; CreateShader::CreateShader (GLenum type, SharedPtr<Shader>& shader, bool useSync, bool serverSync) : Operation ("CreateShader", useSync, serverSync) , m_type (type) { shader = SharedPtr<Shader>(new Shader(getEvent(), getSync())); shader->type = type; m_shader = shader; } void CreateShader::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint shader = 0; thread.newMessage() << "Begin -- glCreateShader(" << m_type << ")" << tcu::ThreadUtil::Message::End; shader = thread.gl.createShader(m_type); GLU_CHECK_GLW_MSG(thread.gl, "glCreateShader()"); thread.newMessage() << "End -- " << shader << " = glCreateShader(" << m_type << ")" << tcu::ThreadUtil::Message::End; m_shader->shader = shader; } class DeleteShader : public Operation { public: DeleteShader (SharedPtr<Shader> shader, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Shader> m_shader; }; DeleteShader::DeleteShader (SharedPtr<Shader> shader, bool useSync, bool serverSync) : Operation ("DeleteShader", useSync, serverSync) , m_shader (shader) { modifyGLObject(SharedPtr<Object>(m_shader)); } void DeleteShader::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint shader = m_shader->shader; thread.newMessage() << "Begin -- glDeleteShader(" << shader << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, deleteShader(shader)); thread.newMessage() << "End -- glDeleteShader()" << tcu::ThreadUtil::Message::End; m_shader->shader = 0; } class ShaderSource : public Operation { public: ShaderSource (SharedPtr<Shader> sharder, const char* source, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Shader> m_shader; string m_source; }; ShaderSource::ShaderSource (SharedPtr<Shader> shader, const char* source, bool useSync, bool serverSync) : Operation ("ShaderSource", useSync, serverSync) , m_shader (shader) , m_source (source) { modifyGLObject(SharedPtr<Object>(m_shader)); m_shader->isDefined = true; } void ShaderSource::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); const char* shaderSource = m_source.c_str(); thread.newMessage() << "Begin -- glShaderSource(" << m_shader->shader << ", 1, \"" << shaderSource << "\", DE_NULL)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, shaderSource(m_shader->shader, 1, &shaderSource, DE_NULL)); thread.newMessage() << "End -- glShaderSource()" << tcu::ThreadUtil::Message::End; } class ShaderCompile : public Operation { public: ShaderCompile (SharedPtr<Shader> sharder, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Shader> m_shader; }; ShaderCompile::ShaderCompile (SharedPtr<Shader> shader, bool useSync, bool serverSync) : Operation ("ShaderCompile", useSync, serverSync) , m_shader (shader) { m_shader->compiled = true; modifyGLObject(SharedPtr<Object>(m_shader)); } void ShaderCompile::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glCompileShader(" << m_shader->shader << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, compileShader(m_shader->shader)); thread.newMessage() << "End -- glCompileShader()" << tcu::ThreadUtil::Message::End; } class Program : public Object { public: Program (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync); // Generation time attributes SharedPtr<Shader> vertexShader; SharedPtr<Shader> fragmentShader; bool linked; // Runtime attributes GLuint program; GLuint runtimeVertexShader; GLuint runtimeFragmentShader; }; Program::Program (SharedPtr<tcu::ThreadUtil::Event> event, SharedPtr<FenceSync> sync) : Object ("Program", event, sync) , linked (false) , program (0) , runtimeVertexShader (0) , runtimeFragmentShader (0) { } class CreateProgram : public Operation { public: CreateProgram (SharedPtr<Program>& program, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; }; CreateProgram::CreateProgram (SharedPtr<Program>& program, bool useSync, bool serverSync) : Operation ("CreateProgram", useSync, serverSync) { program = SharedPtr<Program>(new Program(getEvent(), getSync())); m_program = program; } void CreateProgram::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint program = 0; thread.newMessage() << "Begin -- glCreateProgram()" << tcu::ThreadUtil::Message::End; program = thread.gl.createProgram(); GLU_CHECK_GLW_MSG(thread.gl, "glCreateProgram()"); thread.newMessage() << "End -- " << program << " = glCreateProgram()" << tcu::ThreadUtil::Message::End; m_program->program = program; } class DeleteProgram : public Operation { public: DeleteProgram (SharedPtr<Program> program, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; }; DeleteProgram::DeleteProgram (SharedPtr<Program> program, bool useSync, bool serverSync) : Operation ("DeleteProgram", useSync, serverSync) , m_program (program) { modifyGLObject(SharedPtr<Object>(m_program)); } void DeleteProgram::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint program = m_program->program; thread.newMessage() << "Begin -- glDeleteProgram(" << program << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, deleteProgram(program)); thread.newMessage() << "End -- glDeleteProgram()" << tcu::ThreadUtil::Message::End; m_program->program = 0; } class AttachShader : public Operation { public: AttachShader (SharedPtr<Program> sharder, SharedPtr<Shader> shader, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; SharedPtr<Shader> m_shader; }; AttachShader::AttachShader (SharedPtr<Program> program, SharedPtr<Shader> shader, bool useSync, bool serverSync) : Operation ("AttachShader", useSync, serverSync) , m_program (program) , m_shader (shader) { modifyGLObject(SharedPtr<Object>(m_program)); readGLObject(SharedPtr<Object>(m_shader)); if (m_shader->type == GL_VERTEX_SHADER) m_program->vertexShader = shader; else if (m_shader->type == GL_FRAGMENT_SHADER) m_program->fragmentShader = shader; else DE_ASSERT(false); } void AttachShader::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glAttachShader(" << m_program->program << ", " << m_shader->shader << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, attachShader(m_program->program, m_shader->shader)); thread.newMessage() << "End -- glAttachShader()" << tcu::ThreadUtil::Message::End; if (m_shader->type == GL_VERTEX_SHADER) m_program->runtimeVertexShader = m_shader->shader; else if (m_shader->type == GL_FRAGMENT_SHADER) m_program->runtimeFragmentShader = m_shader->shader; else DE_ASSERT(false); } class DetachShader : public Operation { public: DetachShader (SharedPtr<Program> sharder, GLenum type, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; GLenum m_type; }; DetachShader::DetachShader (SharedPtr<Program> program, GLenum type, bool useSync, bool serverSync) : Operation ("DetachShader", useSync, serverSync) , m_program (program) , m_type (type) { modifyGLObject(SharedPtr<Object>(m_program)); if (m_type == GL_VERTEX_SHADER) { DE_ASSERT(m_program->vertexShader); m_program->vertexShader = SharedPtr<Shader>(); } else if (m_type == GL_FRAGMENT_SHADER) { DE_ASSERT(m_program->fragmentShader); m_program->fragmentShader = SharedPtr<Shader>(); } else DE_ASSERT(false); } void DetachShader::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); if (m_type == GL_VERTEX_SHADER) { thread.newMessage() << "Begin -- glDetachShader(" << m_program->program << ", " << m_program->runtimeVertexShader << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, detachShader(m_program->program, m_program->runtimeVertexShader)); thread.newMessage() << "End -- glDetachShader()" << tcu::ThreadUtil::Message::End; m_program->runtimeVertexShader = 0; } else if (m_type == GL_FRAGMENT_SHADER) { thread.newMessage() << "Begin -- glDetachShader(" << m_program->program << ", " << m_program->runtimeFragmentShader << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, detachShader(m_program->program, m_program->runtimeFragmentShader)); thread.newMessage() << "End -- glDetachShader()" << tcu::ThreadUtil::Message::End; m_program->runtimeFragmentShader = 0; } else DE_ASSERT(false); } class LinkProgram : public Operation { public: LinkProgram (SharedPtr<Program> program, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; }; LinkProgram::LinkProgram (SharedPtr<Program> program, bool useSync, bool serverSync) : Operation ("LinkProgram", useSync, serverSync) , m_program (program) { modifyGLObject(SharedPtr<Object>(m_program)); program->linked = true; } void LinkProgram::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); GLuint program = m_program->program; thread.newMessage() << "Begin -- glLinkProgram(" << program << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, linkProgram(program)); thread.newMessage() << "End -- glLinkProgram()" << tcu::ThreadUtil::Message::End; } class RenderBuffer : public Operation { public: RenderBuffer (SharedPtr<Program> program, SharedPtr<Buffer> buffer, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; SharedPtr<Buffer> m_buffer; }; RenderBuffer::RenderBuffer (SharedPtr<Program> program, SharedPtr<Buffer> buffer, bool useSync, bool serverSync) : Operation ("RenderBuffer", useSync, serverSync) , m_program (program) , m_buffer (buffer) { readGLObject(SharedPtr<Object>(program)); readGLObject(SharedPtr<Object>(buffer)); } void RenderBuffer::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glClearColor(0.5f, 0.5f, 0.5f, 1.0f)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, clearColor(0.5f, 0.5f, 0.5f, 1.0f)); thread.newMessage() << "End -- glClearColor()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glClear(GL_COLOR_BUFFER_BIT)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, clear(GL_COLOR_BUFFER_BIT)); thread.newMessage() << "End -- glClear()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glUseProgram(" << m_program->program << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, useProgram(m_program->program)); thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glGetAttribLocation(" << m_program->program << ", \"a_pos\")" << tcu::ThreadUtil::Message::End; GLint posLoc = thread.gl.getAttribLocation(m_program->program, "a_pos"); GLU_CHECK_GLW_MSG(thread.gl, "glGetAttribLocation()"); thread.newMessage() << "End -- " << posLoc << " = glGetAttribLocation()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glEnableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, enableVertexAttribArray(posLoc)); thread.newMessage() << "End -- glEnableVertexAttribArray()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, " << m_buffer->buffer << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, m_buffer->buffer)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glVertexAttribPointer(" << posLoc << ", GL_BYTE, GL_TRUE, 0, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, vertexAttribPointer(posLoc, 2, GL_BYTE, GL_TRUE, 0, 0)); thread.newMessage() << "End -- glVertexAttribPointer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glDrawArrays(GL_TRIANGLES, 0, " << (m_buffer->size / 2) << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, drawArrays(GL_TRIANGLES, 0, (GLsizei)m_buffer->size / 2)); thread.newMessage() << "End -- glDrawArrays()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, 0)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glDisableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, disableVertexAttribArray(posLoc)); thread.newMessage() << "End -- glDisableVertexAttribArray()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glUseProgram(0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, useProgram(0)); thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End; } class RenderTexture : public Operation { public: RenderTexture (SharedPtr<Program> program, SharedPtr<Texture> texture, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Program> m_program; SharedPtr<Texture> m_texture; }; RenderTexture::RenderTexture (SharedPtr<Program> program, SharedPtr<Texture> texture, bool useSync, bool serverSync) : Operation ("RenderTexture", useSync, serverSync) , m_program (program) , m_texture (texture) { readGLObject(SharedPtr<Object>(program)); readGLObject(SharedPtr<Object>(texture)); } void RenderTexture::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glClearColor(0.5f, 0.5f, 0.5f, 1.0f)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, clearColor(0.5f, 0.5f, 0.5f, 1.0f)); thread.newMessage() << "End -- glClearColor()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glClear(GL_COLOR_BUFFER_BIT)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, clear(GL_COLOR_BUFFER_BIT)); thread.newMessage() << "End -- glClear()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glUseProgram(" << m_program->program << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, useProgram(m_program->program)); thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glGetUniformLocation(" << m_program->program << ", \"u_sampler\")" << tcu::ThreadUtil::Message::End; GLint samplerPos = thread.gl.getUniformLocation(m_program->program, "u_sampler"); GLU_CHECK_GLW_MSG(thread.gl, "glGetUniformLocation()"); thread.newMessage() << "End -- glGetUniformLocation()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glUniform1i(" << samplerPos << ", 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, uniform1i(samplerPos, 0)); thread.newMessage() << "End -- glUniform1i()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glGetAttribLocation(" << m_program->program << ", \"a_pos\")" << tcu::ThreadUtil::Message::End; GLint posLoc = thread.gl.getAttribLocation(m_program->program, "a_pos"); GLU_CHECK_GLW_MSG(thread.gl, "glGetAttribLocation()"); thread.newMessage() << "End -- " << posLoc << " = glGetAttribLocation()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glEnableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, enableVertexAttribArray(posLoc)); thread.newMessage() << "End -- glEnableVertexAttribArray()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, 0)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; float coords[] = { -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0 }; thread.newMessage() << "Begin -- glVertexAttribPointer(" << posLoc << ", GL_FLOAT, GL_FALSE, 0, <data>)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, coords)); thread.newMessage() << "End -- glVertexAttribPointer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glDrawArrays(GL_TRIANGLES, 0, 6)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, drawArrays(GL_TRIANGLES, 0, 6)); thread.newMessage() << "End -- glDrawArrays()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindBuffer(GL_ARRAY_BUFFER, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindBuffer(GL_ARRAY_BUFFER, 0)); thread.newMessage() << "End -- glBindBuffer()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glDisableVertexAttribArray(" << posLoc << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, disableVertexAttribArray(posLoc)); thread.newMessage() << "End -- glDisableVertexAttribArray()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glUseProgram(0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, useProgram(0)); thread.newMessage() << "End -- glUseProgram()" << tcu::ThreadUtil::Message::End; } class ReadPixels : public Operation { public: ReadPixels (int x, int y, int width, int height, GLenum format, GLenum type, SharedPtr<tcu::ThreadUtil::DataBlock>& data, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: int m_x; int m_y; int m_width; int m_height; GLenum m_format; GLenum m_type; SharedPtr<tcu::ThreadUtil::DataBlock> m_data; }; ReadPixels::ReadPixels (int x, int y, int width, int height, GLenum format, GLenum type, SharedPtr<tcu::ThreadUtil::DataBlock>& data, bool useSync, bool serverSync) : Operation ("ReadPixels", useSync, serverSync) , m_x (x) , m_y (y) , m_width (width) , m_height (height) , m_format (format) , m_type (type) { data = SharedPtr<tcu::ThreadUtil::DataBlock>(new tcu::ThreadUtil::DataBlock(getEvent())); m_data = data; } void ReadPixels::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); DE_ASSERT(m_type == GL_UNSIGNED_BYTE); DE_ASSERT(m_format == GL_RGBA); std::vector<deUint8> data((m_width-m_x)*(m_height-m_y)*4); thread.newMessage() << "Begin -- glReadPixels(" << m_x << ", " << m_y << ", " << m_width << ", " << m_height << ", " << m_format << ", " << m_type << ", <data>)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, readPixels(m_x, m_y, m_width, m_height, m_format, m_type, &(data[0]))); thread.newMessage() << "End -- glReadPixels()" << tcu::ThreadUtil::Message::End; m_data->setData(data.size(), &(data[0])); } class CreateImageFromTexture : public Operation { public: // \note [mika] Unlike eglCreateImageKHR this operation requires current context and uses it for creating EGLImage // Current context is required to support EGL sync objects in current tests system CreateImageFromTexture (SharedPtr<EGLImage>& image, SharedPtr<Texture> texture, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; SharedPtr<EGLImage> m_image; }; CreateImageFromTexture::CreateImageFromTexture (SharedPtr<EGLImage>& image, SharedPtr<Texture> texture, bool useSync, bool serverSync) : Operation ("CreateImageFromTexture", useSync, serverSync) { modifyGLObject(SharedPtr<Object>(texture)); image = SharedPtr<EGLImage>(new EGLImage(getEvent(), getSync())); m_image = image; m_texture = texture; m_texture->sourceImage = m_image; } void CreateImageFromTexture::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); EGLint attribList[] = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; // Make texture image complete... thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); thread.newMessage() << "End -- glTexParameteri()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- eglCreateImageKHR(" << thread.runtimeContext->display << ", " << thread.runtimeContext->context << ", EGL_GL_TEXTURE_2D_KHR, " << m_texture->texture << ", { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE })" << tcu::ThreadUtil::Message::End; m_image->image = thread.egl.createImageKHR(thread.runtimeContext->display, thread.runtimeContext->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)m_texture->texture, attribList); EGLU_CHECK_MSG(thread.egl, "eglCreateImageKHR()"); thread.newMessage() << "End -- " << m_image->image << " = eglCreateImageKHR()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; } class DestroyImage : public Operation { public: // \note [mika] Unlike eglDestroyImageKHR this operation requires current context and uses it for creating EGLImage // Current context is required to support EGL sync objects in current tests system DestroyImage (SharedPtr<EGLImage> image, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<EGLImage> m_image; }; DestroyImage::DestroyImage (SharedPtr<EGLImage> image, bool useSync, bool serverSync) : Operation ("CreateImageFromTexture", useSync, serverSync) , m_image (image) { modifyGLObject(SharedPtr<Object>(image)); } void DestroyImage::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- eglDestroyImageKHR(" << thread.runtimeContext->display << ", " << m_image->image << ")" << tcu::ThreadUtil::Message::End; thread.egl.destroyImageKHR(thread.runtimeContext->display, m_image->image); m_image->image = EGL_NO_IMAGE_KHR; EGLU_CHECK_MSG(thread.egl, "eglDestroyImageKHR()"); thread.newMessage() << "End -- eglDestroyImageKHR()" << tcu::ThreadUtil::Message::End; } class DefineTextureFromImage : public Operation { public: DefineTextureFromImage (SharedPtr<Texture> texture, SharedPtr<EGLImage> image, bool useSync, bool serverSync); void exec (tcu::ThreadUtil::Thread& thread); private: SharedPtr<Texture> m_texture; SharedPtr<EGLImage> m_image; }; DefineTextureFromImage::DefineTextureFromImage (SharedPtr<Texture> texture, SharedPtr<EGLImage> image, bool useSync, bool serverSync) : Operation ("DefineTextureFromImage", useSync, serverSync) { readGLObject(SharedPtr<Object>(image)); modifyGLObject(SharedPtr<Object>(texture)); texture->isDefined = true; texture->sourceImage = image; m_image = image; m_texture = texture; } void DefineTextureFromImage::exec (tcu::ThreadUtil::Thread& t) { EGLThread& thread = dynamic_cast<EGLThread&>(t); thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, " << m_texture->texture << ")" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, m_texture->texture)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, " << m_image->image << ")" << tcu::ThreadUtil::Message::End; thread.runtimeContext->glExtensions.imageTargetTexture2D(GL_TEXTURE_2D, m_image->image); GLU_CHECK_GLW_MSG(thread.gl, "glEGLImageTargetTexture2DOES()"); thread.newMessage() << "End -- glEGLImageTargetTexture2DOES()" << tcu::ThreadUtil::Message::End; thread.newMessage() << "Begin -- glBindTexture(GL_TEXTURE_2D, 0)" << tcu::ThreadUtil::Message::End; GLU_CHECK_GLW_CALL(thread.gl, bindTexture(GL_TEXTURE_2D, 0)); thread.newMessage() << "End -- glBindTexture()" << tcu::ThreadUtil::Message::End; } } // GLES2ThreadTest static void requireEGLExtension (const Library& egl, EGLDisplay eglDisplay, const char* requiredExtension) { if (!eglu::hasExtension(egl, eglDisplay, requiredExtension)) TCU_THROW(NotSupportedError, (string(requiredExtension) + " not supported").c_str()); } enum OperationId { THREADOPERATIONID_NONE = 0, THREADOPERATIONID_CREATE_BUFFER, THREADOPERATIONID_DESTROY_BUFFER, THREADOPERATIONID_BUFFER_DATA, THREADOPERATIONID_BUFFER_SUBDATA, THREADOPERATIONID_CREATE_TEXTURE, THREADOPERATIONID_DESTROY_TEXTURE, THREADOPERATIONID_TEXIMAGE2D, THREADOPERATIONID_TEXSUBIMAGE2D, THREADOPERATIONID_COPYTEXIMAGE2D, THREADOPERATIONID_COPYTEXSUBIMAGE2D, THREADOPERATIONID_CREATE_VERTEX_SHADER, THREADOPERATIONID_CREATE_FRAGMENT_SHADER, THREADOPERATIONID_DESTROY_SHADER, THREADOPERATIONID_SHADER_SOURCE, THREADOPERATIONID_SHADER_COMPILE, THREADOPERATIONID_ATTACH_SHADER, THREADOPERATIONID_DETACH_SHADER, THREADOPERATIONID_CREATE_PROGRAM, THREADOPERATIONID_DESTROY_PROGRAM, THREADOPERATIONID_LINK_PROGRAM, THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE, THREADOPERATIONID_DESTROY_IMAGE, THREADOPERATIONID_TEXTURE_FROM_IMAGE, THREADOPERATIONID_LAST }; class GLES2SharingRandomTest : public TestCase { public: struct TestConfig { TestConfig (void); int threadCount; int operationCount; bool serverSync; bool useFenceSync; bool useImages; float probabilities[THREADOPERATIONID_LAST][THREADOPERATIONID_LAST]; }; GLES2SharingRandomTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description); ~GLES2SharingRandomTest (void); void init (void); void deinit (void); IterateResult iterate (void); void addRandomOperation (GLES2ThreadTest::EGLResourceManager& resourceManager); private: TestConfig m_config; int m_seed; de::Random m_random; tcu::TestLog& m_log; bool m_threadsStarted; bool m_threadsRunning; bool m_executionReady; bool m_requiresRestart; deUint64 m_beginTimeUs; deUint64 m_timeOutUs; deUint32 m_sleepTimeMs; deUint64 m_timeOutTimeUs; std::vector<GLES2ThreadTest::EGLThread*> m_threads; EGLDisplay m_eglDisplay; EGLConfig m_eglConfig; OperationId m_lastOperation; glw::Functions m_gl; }; GLES2SharingRandomTest::TestConfig::TestConfig (void) : threadCount (0) , operationCount (0) , serverSync (false) , useFenceSync (false) , useImages (false) { deMemset(probabilities, 0, sizeof(probabilities)); } GLES2SharingRandomTest::GLES2SharingRandomTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description) : TestCase (context, name, description) , m_config (config) , m_seed (deStringHash(name)) , m_random (deStringHash(name)) , m_log (m_testCtx.getLog()) , m_threadsStarted (false) , m_threadsRunning (false) , m_executionReady (false) , m_requiresRestart (false) , m_beginTimeUs (0) , m_timeOutUs (10000000) // 10 seconds , m_sleepTimeMs (1) // 1 milliseconds , m_timeOutTimeUs (0) , m_eglDisplay (EGL_NO_DISPLAY) , m_eglConfig (0) , m_lastOperation (THREADOPERATIONID_NONE) { } GLES2SharingRandomTest::~GLES2SharingRandomTest (void) { GLES2SharingRandomTest::deinit(); } void GLES2SharingRandomTest::init (void) { const Library& egl = m_eglTestCtx.getLibrary(); const EGLint attribList[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_ALPHA_SIZE, 1, EGL_NONE }; m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); m_eglConfig = eglu::chooseSingleConfig(egl, m_eglDisplay, attribList); m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0)); // Check extensions if (m_config.useFenceSync) requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_fence_sync"); if (m_config.serverSync) requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_wait_sync"); if (m_config.useImages) { requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_image_base"); requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_gl_texture_2D_image"); } GLES2ThreadTest::EGLResourceManager resourceManager; // Create contexts for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) { m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed+threadNdx))); SharedPtr<GLES2ThreadTest::GLES2Context> context; SharedPtr<GLES2ThreadTest::GLES2Context> shared = (threadNdx > 0 ? resourceManager.popContext(0) : SharedPtr<GLES2ThreadTest::GLES2Context>()); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, shared, context)); resourceManager.addContext(context); if (shared) resourceManager.addContext(shared); } // Create surfaces for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) { SharedPtr<GLES2ThreadTest::Surface> surface; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface)); resourceManager.addSurface(surface); } // Make contexts current for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) { m_threads[threadNdx]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[threadNdx], m_eglDisplay, resourceManager.popSurface(0), resourceManager.popContext(0))); } // Operations to check fence sync support if (m_config.useFenceSync) { for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) { m_threads[threadNdx]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync")); } } // Init EGLimage support if (m_config.useImages) { for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) { m_threads[threadNdx]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image")); } } // Add random operations for (int operationNdx = 0; operationNdx < m_config.operationCount; operationNdx++) addRandomOperation(resourceManager); { int threadNdx = 0; // Destroy images // \note Android reference counts EGLDisplays so we can't trust the eglTerminate() to clean up resources while (resourceManager.getImageCount() > 0) { const SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(0); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync)); threadNdx = (threadNdx + 1) % m_config.threadCount; } } // Release contexts for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) { SharedPtr<GLES2ThreadTest::GLES2Context> context = m_threads[threadNdx]->context; SharedPtr<GLES2ThreadTest::Surface> surface = m_threads[threadNdx]->surface; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[threadNdx], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>())); resourceManager.addSurface(surface); resourceManager.addContext(context); } // Destroy contexts for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyContext(resourceManager.popContext(0))); // Destroy surfaces for (int threadNdx = 0; threadNdx < m_config.threadCount; threadNdx++) m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, resourceManager.popSurface(0))); } void GLES2SharingRandomTest::deinit (void) { for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { delete m_threads[threadNdx]; m_threads[threadNdx] = DE_NULL; } m_threads.clear(); if (m_eglDisplay != EGL_NO_DISPLAY) { m_eglTestCtx.getLibrary().terminate(m_eglDisplay); m_eglDisplay = EGL_NO_DISPLAY; } TCU_CHECK(!m_requiresRestart); } void GLES2SharingRandomTest::addRandomOperation (GLES2ThreadTest::EGLResourceManager& resourceManager) { int threadNdx = m_random.getUint32() % (deUint32)m_threads.size(); std::vector<OperationId> operations; std::vector<float> weights; operations.push_back(THREADOPERATIONID_CREATE_BUFFER); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_BUFFER]); operations.push_back(THREADOPERATIONID_CREATE_TEXTURE); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_TEXTURE]); operations.push_back(THREADOPERATIONID_CREATE_VERTEX_SHADER); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_VERTEX_SHADER]); operations.push_back(THREADOPERATIONID_CREATE_FRAGMENT_SHADER); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_FRAGMENT_SHADER]); operations.push_back(THREADOPERATIONID_CREATE_PROGRAM); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_PROGRAM]); int destroyableBufferNdx = -1; int destroyableTextureNdx = -1; int destroyableShaderNdx = -1; int destroyableProgramNdx = -1; int vertexShaderNdx = -1; int fragmentShaderNdx = -1; int definedTextureNdx = -1; int definedBufferNdx = -1; int definedShaderNdx = -1; int detachableProgramNdx = -1; GLenum detachShaderType = GL_VERTEX_SHADER; int unusedVertexAttachmentProgramNdx = -1; int unusedFragmentAttachmentProgramNdx = -1; int linkableProgramNdx = -1; int attachProgramNdx = -1; int attachShaderNdx = -1; int nonSiblingTextureNdx = -1; if (m_threads[threadNdx]->context->resourceManager->getBufferCount() > 0) destroyableBufferNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getBufferCount(); if (m_threads[threadNdx]->context->resourceManager->getTextureCount() > 0) destroyableTextureNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getTextureCount(); if (m_threads[threadNdx]->context->resourceManager->getShaderCount() > 0) destroyableShaderNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getShaderCount(); if (m_threads[threadNdx]->context->resourceManager->getProgramCount() > 0) destroyableProgramNdx = m_random.getUint32() % m_threads[threadNdx]->context->resourceManager->getProgramCount(); // Check what kind of buffers we have for (int bufferNdx = 0; bufferNdx < m_threads[threadNdx]->context->resourceManager->getBufferCount(); bufferNdx++) { SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->getBuffer(bufferNdx); if (buffer->isDefined) { if (definedBufferNdx == -1) definedBufferNdx = bufferNdx; else if (m_random.getBool()) definedBufferNdx = bufferNdx; } } // Check what kind of textures we have for (int textureNdx = 0; textureNdx < m_threads[threadNdx]->context->resourceManager->getTextureCount(); textureNdx++) { SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->getTexture(textureNdx); if (texture->isDefined) { if (definedTextureNdx == -1) definedTextureNdx = textureNdx; else if (m_random.getBool()) definedTextureNdx = textureNdx; if (!texture->sourceImage) { if (nonSiblingTextureNdx == -1) nonSiblingTextureNdx = textureNdx; else if (m_random.getBool()) nonSiblingTextureNdx = textureNdx; } } } // Check what kind of shaders we have for (int shaderNdx = 0; shaderNdx < m_threads[threadNdx]->context->resourceManager->getShaderCount(); shaderNdx++) { SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->getShader(shaderNdx); // Defined shader found if (shader->isDefined) { if (definedShaderNdx == -1) definedShaderNdx = shaderNdx; else if (m_random.getBool()) definedShaderNdx = shaderNdx; } // Vertex shader found if (shader->type == GL_VERTEX_SHADER) { if (vertexShaderNdx == -1) vertexShaderNdx = shaderNdx; else if (m_random.getBool()) vertexShaderNdx = shaderNdx; } // Fragmet shader found if (shader->type == GL_FRAGMENT_SHADER) { if (fragmentShaderNdx == -1) fragmentShaderNdx = shaderNdx; else if (m_random.getBool()) fragmentShaderNdx = shaderNdx; } } // Check what kind of programs we have for (int programNdx = 0; programNdx < m_threads[threadNdx]->context->resourceManager->getProgramCount(); programNdx++) { SharedPtr<GLES2ThreadTest::Program> program = m_threads[threadNdx]->context->resourceManager->getProgram(programNdx); // Program that can be detached if (program->vertexShader || program->fragmentShader) { if (detachableProgramNdx == -1) { detachableProgramNdx = programNdx; if (program->vertexShader) detachShaderType = GL_VERTEX_SHADER; else if (program->fragmentShader) detachShaderType = GL_FRAGMENT_SHADER; else DE_ASSERT(false); } else if (m_random.getBool()) { detachableProgramNdx = programNdx; if (program->vertexShader) detachShaderType = GL_VERTEX_SHADER; else if (program->fragmentShader) detachShaderType = GL_FRAGMENT_SHADER; else DE_ASSERT(false); } } // Program that can be attached vertex shader if (!program->vertexShader) { if (unusedVertexAttachmentProgramNdx == -1) unusedVertexAttachmentProgramNdx = programNdx; else if (m_random.getBool()) unusedVertexAttachmentProgramNdx = programNdx; } // Program that can be attached fragment shader if (!program->fragmentShader) { if (unusedFragmentAttachmentProgramNdx == -1) unusedFragmentAttachmentProgramNdx = programNdx; else if (m_random.getBool()) unusedFragmentAttachmentProgramNdx = programNdx; } // Program that can be linked if (program->vertexShader && program->fragmentShader) { if (linkableProgramNdx == -1) linkableProgramNdx = programNdx; else if (m_random.getBool()) linkableProgramNdx = programNdx; } } // Has images if (resourceManager.getImageCount() > 0) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_IMAGE]); operations.push_back(THREADOPERATIONID_DESTROY_IMAGE); if (m_threads[threadNdx]->context->resourceManager->getTextureCount() > 0) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXTURE_FROM_IMAGE]); operations.push_back(THREADOPERATIONID_TEXTURE_FROM_IMAGE); } } // Has buffer if (destroyableBufferNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_BUFFER]); operations.push_back(THREADOPERATIONID_DESTROY_BUFFER); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_BUFFER_DATA]); operations.push_back(THREADOPERATIONID_BUFFER_DATA); } // Has buffer with defined data if (definedBufferNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_BUFFER_SUBDATA]); operations.push_back(THREADOPERATIONID_BUFFER_SUBDATA); } // Has texture if (destroyableTextureNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_TEXTURE]); operations.push_back(THREADOPERATIONID_DESTROY_TEXTURE); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXIMAGE2D]); operations.push_back(THREADOPERATIONID_TEXIMAGE2D); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_COPYTEXIMAGE2D]); operations.push_back(THREADOPERATIONID_COPYTEXIMAGE2D); } // Has texture with data if (definedTextureNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_TEXSUBIMAGE2D]); operations.push_back(THREADOPERATIONID_TEXSUBIMAGE2D); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_COPYTEXSUBIMAGE2D]); operations.push_back(THREADOPERATIONID_COPYTEXSUBIMAGE2D); } // Has texture that can be used as EGLimage source if (nonSiblingTextureNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE]); operations.push_back(THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE); } // Has shader if (destroyableShaderNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_SHADER]); operations.push_back(THREADOPERATIONID_DESTROY_SHADER); weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_SHADER_SOURCE]); operations.push_back(THREADOPERATIONID_SHADER_SOURCE); } // Has shader with defined source if (definedShaderNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_SHADER_COMPILE]); operations.push_back(THREADOPERATIONID_SHADER_COMPILE); } // Has program if (destroyableProgramNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DESTROY_PROGRAM]); operations.push_back(THREADOPERATIONID_DESTROY_PROGRAM); } // Has program that can be linked if (linkableProgramNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_LINK_PROGRAM]); operations.push_back(THREADOPERATIONID_LINK_PROGRAM); } // has program with attachments if (detachableProgramNdx != -1) { weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_DETACH_SHADER]); operations.push_back(THREADOPERATIONID_DETACH_SHADER); } // Has program and shader pair that can be attached if (fragmentShaderNdx != -1 && unusedFragmentAttachmentProgramNdx != -1) { if (attachProgramNdx == -1) { DE_ASSERT(attachShaderNdx == -1); attachProgramNdx = unusedFragmentAttachmentProgramNdx; attachShaderNdx = fragmentShaderNdx; weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_ATTACH_SHADER]); operations.push_back(THREADOPERATIONID_ATTACH_SHADER); } else if (m_random.getBool()) { attachProgramNdx = unusedFragmentAttachmentProgramNdx; attachShaderNdx = fragmentShaderNdx; } } if (vertexShaderNdx != -1 && unusedVertexAttachmentProgramNdx != -1) { if (attachProgramNdx == -1) { DE_ASSERT(attachShaderNdx == -1); attachProgramNdx = unusedVertexAttachmentProgramNdx; attachShaderNdx = vertexShaderNdx; weights.push_back(m_config.probabilities[m_lastOperation][THREADOPERATIONID_ATTACH_SHADER]); operations.push_back(THREADOPERATIONID_ATTACH_SHADER); } else if (m_random.getBool()) { attachProgramNdx = unusedVertexAttachmentProgramNdx; attachShaderNdx = vertexShaderNdx; } } OperationId op = m_random.chooseWeighted<OperationId, std::vector<OperationId> ::iterator>(operations.begin(), operations.end(), weights.begin()); switch (op) { case THREADOPERATIONID_CREATE_BUFFER: { SharedPtr<GLES2ThreadTest::Buffer> buffer; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateBuffer(buffer, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addBuffer(buffer); break; } case THREADOPERATIONID_DESTROY_BUFFER: { SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(destroyableBufferNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync)); break; } case THREADOPERATIONID_BUFFER_DATA: { SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(destroyableBufferNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addBuffer(buffer); break; } case THREADOPERATIONID_BUFFER_SUBDATA: { SharedPtr<GLES2ThreadTest::Buffer> buffer = m_threads[threadNdx]->context->resourceManager->popBuffer(definedBufferNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 1, 20, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addBuffer(buffer); break; } case THREADOPERATIONID_CREATE_TEXTURE: { SharedPtr<GLES2ThreadTest::Texture> texture; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addTexture(texture); break; } case THREADOPERATIONID_DESTROY_TEXTURE: m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteTexture(m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx), m_config.useFenceSync, m_config.serverSync)); break; case THREADOPERATIONID_TEXIMAGE2D: { SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addTexture(texture); break; } case THREADOPERATIONID_TEXSUBIMAGE2D: { SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(definedTextureNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 30, 30, 50, 50, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addTexture(texture); break; } case THREADOPERATIONID_COPYTEXIMAGE2D: { SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 20, 20, 300, 300, 0, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addTexture(texture); break; } case THREADOPERATIONID_COPYTEXSUBIMAGE2D: { SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(definedTextureNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 10, 10, 30, 30, 50, 50, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addTexture(texture); break; } case THREADOPERATIONID_CREATE_VERTEX_SHADER: { SharedPtr<GLES2ThreadTest::Shader> shader; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, shader, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addShader(shader); break; } case THREADOPERATIONID_CREATE_FRAGMENT_SHADER: { SharedPtr<GLES2ThreadTest::Shader> shader; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, shader, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addShader(shader); break; } case THREADOPERATIONID_DESTROY_SHADER: m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteShader(m_threads[threadNdx]->context->resourceManager->popShader(destroyableShaderNdx), m_config.useFenceSync, m_config.serverSync)); break; case THREADOPERATIONID_SHADER_SOURCE: { const char* vertexShaderSource = "attribute mediump vec4 a_pos;\n" "varying mediump vec4 v_pos;\n" "void main (void)\n" "{\n" "\tv_pos = a_pos;\n" "\tgl_Position = a_pos;\n" "}\n"; const char* fragmentShaderSource = "varying mediump vec4 v_pos;\n" "void main (void)\n" "{\n" "\tgl_FragColor = v_pos;\n" "}\n"; SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(destroyableShaderNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (shader->type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addShader(shader); break; } case THREADOPERATIONID_SHADER_COMPILE: { SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(definedShaderNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addShader(shader); break; } case THREADOPERATIONID_CREATE_PROGRAM: { SharedPtr<GLES2ThreadTest::Program> program; m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addProgram(program); break; } case THREADOPERATIONID_DESTROY_PROGRAM: m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DeleteProgram(m_threads[threadNdx]->context->resourceManager->popProgram(destroyableProgramNdx), m_config.useFenceSync, m_config.serverSync)); break; case THREADOPERATIONID_ATTACH_SHADER: { SharedPtr<GLES2ThreadTest::Program> program = m_threads[threadNdx]->context->resourceManager->popProgram(attachProgramNdx); SharedPtr<GLES2ThreadTest::Shader> shader = m_threads[threadNdx]->context->resourceManager->popShader(attachShaderNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::AttachShader(program, shader, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addProgram(program); m_threads[threadNdx]->context->resourceManager->addShader(shader); break; } case THREADOPERATIONID_DETACH_SHADER: { SharedPtr<GLES2ThreadTest::Program> program = m_threads[threadNdx]->context->resourceManager->popProgram(detachableProgramNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DetachShader(program, detachShaderType, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addProgram(program); break; } case THREADOPERATIONID_LINK_PROGRAM: { SharedPtr<GLES2ThreadTest::Program> program = m_threads[threadNdx]->context->resourceManager->popProgram(linkableProgramNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addProgram(program); break; } case THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE: { SharedPtr<GLES2ThreadTest::EGLImage> image; SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(nonSiblingTextureNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, texture, m_config.useFenceSync, m_config.serverSync)); // \note [mika] Can source be added back to resourceManager? m_threads[threadNdx]->context->resourceManager->addTexture(texture); resourceManager.addImage(image); break; } case THREADOPERATIONID_DESTROY_IMAGE: { int imageNdx = m_random.getInt(0, resourceManager.getImageCount()-1); SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(imageNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync)); break; } case THREADOPERATIONID_TEXTURE_FROM_IMAGE: { int imageNdx = m_random.getInt(0, resourceManager.getImageCount()-1); SharedPtr<GLES2ThreadTest::Texture> texture = m_threads[threadNdx]->context->resourceManager->popTexture(destroyableTextureNdx); SharedPtr<GLES2ThreadTest::EGLImage> image = resourceManager.popImage(imageNdx); m_threads[threadNdx]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync)); m_threads[threadNdx]->context->resourceManager->addTexture(texture); resourceManager.addImage(image); break; } default: DE_ASSERT(false); } m_lastOperation = op; } tcu::TestCase::IterateResult GLES2SharingRandomTest::iterate (void) { if (!m_threadsStarted) { m_beginTimeUs = deGetMicroseconds(); // Execute threads for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) m_threads[threadNdx]->exec(); m_threadsStarted = true; m_threadsRunning = true; } if (m_threadsRunning) { // Wait threads to finish int readyThreads = 0; for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus(); if (status != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING && status != tcu::ThreadUtil::Thread::THREADSTATUS_NOT_STARTED) readyThreads++; } if (readyThreads == (int)m_threads.size()) { for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) m_threads[threadNdx]->join(); m_executionReady = true; m_requiresRestart = false; } if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs) { for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING) { if (m_threads[threadNdx]->isStarted()) m_threads[threadNdx]->join(); } } m_executionReady = true; m_requiresRestart = true; m_timeOutTimeUs = deGetMicroseconds(); } else { deSleep(m_sleepTimeMs); } } if (m_executionReady) { std::vector<int> indices(m_threads.size(), 0); if (m_timeOutTimeUs != 0) m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage; while (true) { int firstThread = -1; // Find first thread with messages for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx]) { firstThread = threadNdx; break; } } // No more messages if (firstThread == -1) break; for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { // No more messages in this thread if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx]) continue; if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs)) firstThread = threadNdx; } tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]); m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage; indices[firstThread]++; } if (m_timeOutTimeUs != 0) m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage; bool isOk = true; bool notSupported = false; for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus(); switch (status) { case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED: case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED: case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING: isOk = false; break; case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED: notSupported = true; break; case tcu::ThreadUtil::Thread::THREADSTATUS_READY: // Nothing break; default: DE_ASSERT(false); isOk = false; }; } if (notSupported) throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__); if (isOk) m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); else m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); return STOP; } return CONTINUE; } class GLES2ThreadedSharingTest : public TestCase { public: struct TestConfig { enum ResourceType { RESOURCETYPE_BUFFER = 0, RESOURCETYPE_TEXTURE, RESOURCETYPE_VERTEX_SHADER, RESOURCETYPE_FRAGMENT_SHADER, RESOURCETYPE_PROGRAM, RESOURCETYPE_IMAGE }; ResourceType resourceType; bool singleContext; int define; int modify; bool useFenceSync; bool serverSync; bool render; }; GLES2ThreadedSharingTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description); ~GLES2ThreadedSharingTest (void); void init (void); void deinit (void); IterateResult iterate (void); void addBufferOperations (void); void addTextureOperations (void); void addImageOperations (void); void addShaderOperations (GLenum type); void addProgramOperations (void); private: TestConfig m_config; tcu::TestLog& m_log; int m_seed; bool m_threadsStarted; bool m_threadsRunning; bool m_executionReady; bool m_requiresRestart; deUint64 m_beginTimeUs; deUint64 m_timeOutUs; deUint32 m_sleepTimeMs; deUint64 m_timeOutTimeUs; std::vector<GLES2ThreadTest::EGLThread*> m_threads; EGLDisplay m_eglDisplay; EGLConfig m_eglConfig; glw::Functions m_gl; }; GLES2ThreadedSharingTest::GLES2ThreadedSharingTest (EglTestContext& context, const TestConfig& config, const char* name, const char* description) : TestCase (context, name, description) , m_config (config) , m_log (m_testCtx.getLog()) , m_seed (deStringHash(name)) , m_threadsStarted (false) , m_threadsRunning (false) , m_executionReady (false) , m_requiresRestart (false) , m_beginTimeUs (0) , m_timeOutUs (10000000) // 10 seconds , m_sleepTimeMs (1) // 1 milliseconds , m_timeOutTimeUs (0) , m_eglDisplay (EGL_NO_DISPLAY) , m_eglConfig (0) { } GLES2ThreadedSharingTest::~GLES2ThreadedSharingTest (void) { GLES2ThreadedSharingTest::deinit(); } void GLES2ThreadedSharingTest::init (void) { const Library& egl = m_eglTestCtx.getLibrary(); const EGLint attribList[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_ALPHA_SIZE, 1, EGL_NONE }; m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); m_eglConfig = eglu::chooseSingleConfig(egl, m_eglDisplay, attribList); m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0)); // Check extensions if (m_config.useFenceSync) requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_fence_sync"); if (m_config.serverSync) requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_wait_sync"); if (m_config.resourceType == TestConfig::RESOURCETYPE_IMAGE) { requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_image_base"); requireEGLExtension(egl, m_eglDisplay, "EGL_KHR_gl_texture_2D_image"); } // Create threads m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed))); m_threads.push_back(new GLES2ThreadTest::EGLThread(egl, m_gl, deInt32Hash(m_seed*200))); SharedPtr<GLES2ThreadTest::GLES2Context> contex1; SharedPtr<GLES2ThreadTest::GLES2Context> contex2; SharedPtr<GLES2ThreadTest::Surface> surface1; SharedPtr<GLES2ThreadTest::Surface> surface2; // Create contexts m_threads[0]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, SharedPtr<GLES2ThreadTest::GLES2Context>(), contex1)); m_threads[1]->addOperation(new GLES2ThreadTest::CreateContext(m_eglDisplay, m_eglConfig, contex1, contex2)); // Create surfaces m_threads[0]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface1)); m_threads[1]->addOperation(new GLES2ThreadTest::CreatePBufferSurface(m_eglDisplay, m_eglConfig, 400, 400, surface2)); // Make current contexts m_threads[0]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, surface1, contex1)); m_threads[1]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[1], m_eglDisplay, surface2, contex2)); // Operations to check fence sync support if (m_config.useFenceSync) { m_threads[0]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync")); m_threads[1]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_sync")); } switch (m_config.resourceType) { case TestConfig::RESOURCETYPE_BUFFER: addBufferOperations(); break; case TestConfig::RESOURCETYPE_TEXTURE: addTextureOperations(); break; case TestConfig::RESOURCETYPE_IMAGE: addImageOperations(); break; case TestConfig::RESOURCETYPE_VERTEX_SHADER: addShaderOperations(GL_VERTEX_SHADER); break; case TestConfig::RESOURCETYPE_FRAGMENT_SHADER: addShaderOperations(GL_FRAGMENT_SHADER); break; case TestConfig::RESOURCETYPE_PROGRAM: addProgramOperations(); break; default: DE_ASSERT(false); } // Relaese contexts m_threads[0]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>())); m_threads[1]->addOperation(new GLES2ThreadTest::MakeCurrent(*m_threads[0], m_eglDisplay, SharedPtr<GLES2ThreadTest::Surface>(), SharedPtr<GLES2ThreadTest::GLES2Context>())); // Destory context m_threads[0]->addOperation(new GLES2ThreadTest::DestroyContext(contex1)); m_threads[1]->addOperation(new GLES2ThreadTest::DestroyContext(contex2)); // Destroy surfaces m_threads[0]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, surface1)); m_threads[1]->addOperation(new GLES2ThreadTest::DestroySurface(m_eglDisplay, surface2)); } void GLES2ThreadedSharingTest::addBufferOperations (void) { // Add operations for verify SharedPtr<GLES2ThreadTest::Shader> vertexShader; SharedPtr<GLES2ThreadTest::Shader> fragmentShader; SharedPtr<GLES2ThreadTest::Program> program; if (m_config.render) { const char* vertexShaderSource = "attribute highp vec2 a_pos;\n" "varying mediump vec2 v_pos;\n" "void main(void)\n" "{\n" "\tv_pos = a_pos;\n" "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" "}\n"; const char* fragmentShaderSource = "varying mediump vec2 v_pos;\n" "void main(void)\n" "{\n" "\tgl_FragColor = vec4(v_pos, 0.5, 1.0);\n" "}\n"; m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync)); } SharedPtr<GLES2ThreadTest::Buffer> buffer; m_threads[0]->addOperation(new GLES2ThreadTest::CreateBuffer(buffer, m_config.useFenceSync, m_config.serverSync)); if (m_config.define) { if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::BufferData(buffer, GL_ARRAY_BUFFER, 1024, GL_DYNAMIC_DRAW, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify) { if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 17, 17, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::BufferSubData(buffer, GL_ARRAY_BUFFER, 17, 17, m_config.useFenceSync, m_config.serverSync)); } if (m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::RenderBuffer(program, buffer, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::RenderBuffer(program, buffer, m_config.useFenceSync, m_config.serverSync)); SharedPtr<tcu::ThreadUtil::DataBlock> pixels1; SharedPtr<tcu::ThreadUtil::DataBlock> pixels2; m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2)); } if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DeleteBuffer(buffer, m_config.useFenceSync, m_config.serverSync)); if (m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync)); } } void GLES2ThreadedSharingTest::addTextureOperations (void) { // Add operations for verify SharedPtr<GLES2ThreadTest::Shader> vertexShader; SharedPtr<GLES2ThreadTest::Shader> fragmentShader; SharedPtr<GLES2ThreadTest::Program> program; if (m_config.render) { const char* vertexShaderSource = "attribute highp vec2 a_pos;\n" "varying mediump vec2 v_pos;\n" "void main(void)\n" "{\n" "\tv_pos = a_pos;\n" "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" "}\n"; const char* fragmentShaderSource = "varying mediump vec2 v_pos;\n" "uniform sampler2D u_sampler;\n" "void main(void)\n" "{\n" "\tgl_FragColor = texture2D(u_sampler, v_pos);\n" "}\n"; m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync)); } SharedPtr<GLES2ThreadTest::Texture> texture; m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync)); if (m_config.define == 1) { if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); } if (m_config.define == 2) { if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 17, 17, 256, 256, 0, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 17, 17, 256, 256, 0, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify == 1) { if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify == 2) { if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync)); } if (m_config.render) { SharedPtr<tcu::ThreadUtil::DataBlock> pixels1; SharedPtr<tcu::ThreadUtil::DataBlock> pixels2; m_threads[0]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2)); } if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync)); if (m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync)); } } void GLES2ThreadedSharingTest::addImageOperations (void) { // Add operations for verify SharedPtr<GLES2ThreadTest::Shader> vertexShader; SharedPtr<GLES2ThreadTest::Shader> fragmentShader; SharedPtr<GLES2ThreadTest::Program> program; m_threads[0]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image")); m_threads[1]->addOperation(new GLES2ThreadTest::InitGLExtension("GL_OES_EGL_image")); if (m_config.render) { const char* vertexShaderSource = "attribute highp vec2 a_pos;\n" "varying mediump vec2 v_pos;\n" "void main(void)\n" "{\n" "\tv_pos = a_pos;\n" "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" "}\n"; const char* fragmentShaderSource = "varying mediump vec2 v_pos;\n" "uniform sampler2D u_sampler;\n" "void main(void)\n" "{\n" "\tgl_FragColor = texture2D(u_sampler, v_pos);\n" "}\n"; m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync)); } SharedPtr<GLES2ThreadTest::Texture> sourceTexture; SharedPtr<GLES2ThreadTest::Texture> texture; SharedPtr<GLES2ThreadTest::EGLImage> image; m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(sourceTexture, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(sourceTexture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); if (m_config.define == 1) { if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync)); } if (m_config.define == 2) { m_threads[0]->addOperation(new GLES2ThreadTest::CreateImageFromTexture(image, sourceTexture, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateTexture(texture, m_config.useFenceSync, m_config.serverSync)); if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DefineTextureFromImage(texture, image, m_config.useFenceSync, m_config.serverSync)); } m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(sourceTexture, m_config.useFenceSync, m_config.serverSync)); if (m_config.modify == 1) { DE_ASSERT(m_config.define != 1); if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::TexSubImage2D(texture, 0, 17, 17, 29, 29, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify == 2) { DE_ASSERT(m_config.define != 1); if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexSubImage2D(texture, 0, 7, 7, 17, 17, 29, 29, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify == 3) { DE_ASSERT(m_config.define != 1); if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::TexImage2D(texture, 0, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify == 4) { DE_ASSERT(m_config.define != 1); if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 7, 7, 256, 256, 0, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::CopyTexImage2D(texture, 0, GL_RGBA, 7, 7, 256, 256, 0, m_config.useFenceSync, m_config.serverSync)); } if (m_config.render) { DE_ASSERT(m_config.define != 1); SharedPtr<tcu::ThreadUtil::DataBlock> pixels1; SharedPtr<tcu::ThreadUtil::DataBlock> pixels2; m_threads[0]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::RenderTexture(program, texture, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels1, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::ReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, pixels2, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new tcu::ThreadUtil::CompareData(pixels1, pixels2)); } if (texture) { if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DeleteTexture(texture, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DestroyImage(image, m_config.useFenceSync, m_config.serverSync)); if (m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync)); } } void GLES2ThreadedSharingTest::addShaderOperations (GLenum type) { SharedPtr<GLES2ThreadTest::Shader> shader; m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(type, shader, m_config.useFenceSync, m_config.serverSync)); if (m_config.define) { const char* vertexShaderSource = "attribute mediump vec4 a_pos;\n" "void main(void)\n" "{\n" "\tgl_Position = a_pos;\n" "}"; const char* fragmentShaderSource = "void main(void)\n" "{\n" "\tgl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}"; if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::ShaderSource(shader, (type == GL_VERTEX_SHADER ? vertexShaderSource : fragmentShaderSource), m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify) { if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::ShaderCompile(shader, m_config.useFenceSync, m_config.serverSync)); } DE_ASSERT(!m_config.render); if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(shader, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DeleteShader(shader, m_config.useFenceSync, m_config.serverSync)); } void GLES2ThreadedSharingTest::addProgramOperations (void) { // Add operations for verify SharedPtr<GLES2ThreadTest::Shader> vertexShader; SharedPtr<GLES2ThreadTest::Shader> fragmentShader; if (m_config.define) { const char* vertexShaderSource = "attribute highp vec2 a_pos;\n" "varying mediump vec2 v_pos;\n" "void main(void)\n" "{\n" "\tv_pos = a_pos;\n" "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" "}\n"; const char* fragmentShaderSource = "varying mediump vec2 v_pos;\n" "void main(void)\n" "{\n" "\tgl_FragColor = vec4(v_pos, 0.5, 1.0);\n" "}\n"; m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_VERTEX_SHADER, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(vertexShader, vertexShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::CreateShader(GL_FRAGMENT_SHADER, fragmentShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderSource(fragmentShader, fragmentShaderSource, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::ShaderCompile(fragmentShader, m_config.useFenceSync, m_config.serverSync)); } SharedPtr<GLES2ThreadTest::Program> program; m_threads[0]->addOperation(new GLES2ThreadTest::CreateProgram(program, m_config.useFenceSync, m_config.serverSync)); if (m_config.define) { // Attach shaders if (m_config.modify || m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync)); } else { m_threads[1]->addOperation(new GLES2ThreadTest::AttachShader(program, vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::AttachShader(program, fragmentShader, m_config.useFenceSync, m_config.serverSync)); } } if (m_config.modify == 1) { // Link program if (m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::LinkProgram(program, m_config.useFenceSync, m_config.serverSync)); } if (m_config.modify == 2) { // Link program if (m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_VERTEX_SHADER, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_FRAGMENT_SHADER, m_config.useFenceSync, m_config.serverSync)); } else { m_threads[1]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_VERTEX_SHADER, m_config.useFenceSync, m_config.serverSync)); m_threads[1]->addOperation(new GLES2ThreadTest::DetachShader(program, GL_FRAGMENT_SHADER, m_config.useFenceSync, m_config.serverSync)); } } if (m_config.render) { DE_ASSERT(false); } if (m_config.modify || m_config.render) m_threads[0]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync)); else m_threads[1]->addOperation(new GLES2ThreadTest::DeleteProgram(program, m_config.useFenceSync, m_config.serverSync)); if (m_config.render) { m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(vertexShader, m_config.useFenceSync, m_config.serverSync)); m_threads[0]->addOperation(new GLES2ThreadTest::DeleteShader(fragmentShader, m_config.useFenceSync, m_config.serverSync)); } } void GLES2ThreadedSharingTest::deinit (void) { for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { delete m_threads[threadNdx]; m_threads[threadNdx] = DE_NULL; } m_threads.clear(); if (m_eglDisplay != EGL_NO_DISPLAY) { m_eglTestCtx.getLibrary().terminate(m_eglDisplay); m_eglDisplay = EGL_NO_DISPLAY; } TCU_CHECK(!m_requiresRestart); } tcu::TestCase::IterateResult GLES2ThreadedSharingTest::iterate (void) { if (!m_threadsStarted) { m_beginTimeUs = deGetMicroseconds(); // Execute threads for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) m_threads[threadNdx]->exec(); m_threadsStarted = true; m_threadsRunning = true; } if (m_threadsRunning) { // Wait threads to finish int readyThreads = 0; for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING) readyThreads++; } if (readyThreads == (int)m_threads.size()) { for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) m_threads[threadNdx]->join(); m_executionReady = true; m_requiresRestart = false; } if (deGetMicroseconds() - m_beginTimeUs > m_timeOutUs) { for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { if (m_threads[threadNdx]->getStatus() != tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING) m_threads[threadNdx]->join(); } m_executionReady = true; m_requiresRestart = true; m_timeOutTimeUs = deGetMicroseconds(); } else { deSleep(m_sleepTimeMs); } } if (m_executionReady) { std::vector<int> indices(m_threads.size(), 0); if (m_timeOutTimeUs != 0) m_log << tcu::TestLog::Message << "Execution timeout limit reached. Trying to get per thread logs. This is potentially dangerous." << tcu::TestLog::EndMessage; while (true) { int firstThread = -1; // Find first thread with messages for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { if (m_threads[threadNdx]->getMessageCount() > indices[threadNdx]) { firstThread = threadNdx; break; } } // No more messages if (firstThread == -1) break; for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { // No more messages in this thread if (m_threads[threadNdx]->getMessageCount() <= indices[threadNdx]) continue; if ((m_threads[threadNdx]->getMessage(indices[threadNdx]).getTime() - m_beginTimeUs) < (m_threads[firstThread]->getMessage(indices[firstThread]).getTime() - m_beginTimeUs)) firstThread = threadNdx; } tcu::ThreadUtil::Message message = m_threads[firstThread]->getMessage(indices[firstThread]); m_log << tcu::TestLog::Message << "[" << (message.getTime() - m_beginTimeUs) << "] (" << firstThread << ") " << message.getMessage() << tcu::TestLog::EndMessage; indices[firstThread]++; } if (m_timeOutTimeUs != 0) m_log << tcu::TestLog::Message << "[" << (m_timeOutTimeUs - m_beginTimeUs) << "] Execution timeout limit reached" << tcu::TestLog::EndMessage; bool isOk = true; bool notSupported = false; for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++) { const tcu::ThreadUtil::Thread::ThreadStatus status = m_threads[threadNdx]->getStatus(); switch (status) { case tcu::ThreadUtil::Thread::THREADSTATUS_FAILED: case tcu::ThreadUtil::Thread::THREADSTATUS_INIT_FAILED: case tcu::ThreadUtil::Thread::THREADSTATUS_RUNNING: isOk = false; break; case tcu::ThreadUtil::Thread::THREADSTATUS_NOT_SUPPORTED: notSupported = true; break; case tcu::ThreadUtil::Thread::THREADSTATUS_READY: // Nothing break; default: DE_ASSERT(false); isOk = false; }; } if (notSupported) throw tcu::NotSupportedError("Thread threw tcu::NotSupportedError", "", __FILE__, __LINE__); if (isOk) m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); else m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); return STOP; } return CONTINUE; } static void addSimpleTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync) { { TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests"); { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 0; config.modify = 0; config.render = false; bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete buffer")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = false; bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata", "Generate, set data and delete buffer")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = false; bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata", "Generate, set data, update data and delete buffer")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = true; bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "bufferdata_render", "Generate, set data, render and delete buffer")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_BUFFER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = true; bufferTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "buffersubdata_render", "Generate, set data, update data, render and delete buffer")); } group->addChild(bufferTests); } { TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests"); { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 0; config.modify = 0; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "gen_delete", "Generate and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Generate, set data and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d", "Generate, set data, update data and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 2; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = true; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Generate, set data, render and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = true; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 2; config.render = true; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 0; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Generate, set data and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 1; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d", "Generate, set data, update data and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 2; config.render = false; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d", "Generate, set data, update data and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 0; config.render = true; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Generate, set data, render and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 1; config.render = true; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_texsubimage2d_render", "Generate, set data, update data, render and delete texture")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_TEXTURE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 2; config.render = true; textureTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_copytexsubimage2d_render", "Generate, set data, update data, render and delete texture")); } group->addChild(textureTests); } { TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests"); { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 0; config.modify = 0; config.render = false; shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_create_destroy", "Create and delete shader")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = false; shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_shadersource", "Create, set source and delete shader")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_VERTEX_SHADER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = false; shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "vtx_compile", "Create, set source, compile and delete shader")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 0; config.modify = 0; config.render = false; shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_create_destroy", "Create and delete shader")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = false; shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_shadersource", "Create, set source and delete shader")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_FRAGMENT_SHADER; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = false; shaderTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "frag_compile", "Create, set source, compile and delete shader")); } group->addChild(shaderTests); } { TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests"); { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 0; config.modify = 0; config.render = false; programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and delete program")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = false; programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "attach", "Create, attach shaders and delete program")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_PROGRAM; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 1; config.render = false; programTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "link", "Create, attach shaders, link and delete program")); } group->addChild(programTests); } { TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests"); TestCaseGroup* textureSourceTests = new TestCaseGroup(ctx, "texture_source", "Image management tests with texture source."); { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 1; config.modify = 0; config.render = false; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_destroy", "Create and destroy EGLImage.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 0; config.render = false; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture", "Create texture from image.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 1; config.render = false; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d", "Modify texture created from image with glTexSubImage2D.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 2; config.render = false; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d", "Modify texture created from image with glCopyTexSubImage2D.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 3; config.render = false; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d", "Modify texture created from image with glTexImage2D.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 4; config.render = false; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d", "Modify texture created from image with glCopyTexImage2D.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 0; config.render = true; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "create_texture_render", "Create texture from image and render.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 1; config.render = true; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "texsubimage2d_render", "Modify texture created from image and render.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 2; config.render = true; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copytexsubimage2d_render", "Modify texture created from image and render.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 3; config.render = true; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "teximage2d_render", "Modify texture created from image and render.")); } { GLES2ThreadedSharingTest::TestConfig config; config.resourceType = GLES2ThreadedSharingTest::TestConfig::RESOURCETYPE_IMAGE; config.useFenceSync = useSync; config.serverSync = serverSync; config.define = 2; config.modify = 4; config.render = true; textureSourceTests->addChild(new GLES2ThreadedSharingTest(ctx, config, "copyteximage2d_render", "Modify texture created from image and render.")); } imageTests->addChild(textureSourceTests); group->addChild(imageTests); } } static void addRandomTests (EglTestContext& ctx, tcu::TestCaseGroup* group, bool useSync, bool serverSync) { { TestCaseGroup* textureTests = new TestCaseGroup(ctx, "textures", "Texture management tests"); { TestCaseGroup* genTextureTests = new TestCaseGroup(ctx, "gen_delete", "Texture gen and delete tests"); for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + textureTestNdx % 5; config.operationCount = 30 + textureTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.75f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.5f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.5f; std::string name = de::toString(textureTestNdx); genTextureTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } textureTests->addChild(genTextureTests); } { TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Texture gen, delete and teximage2D tests"); for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + textureTestNdx % 5; config.operationCount = 40 + textureTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.80f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.20f; std::string name = de::toString(textureTestNdx); texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } textureTests->addChild(texImage2DTests); } { TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Texture gen, delete, teximage2D and texsubimage2d tests"); for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + textureTestNdx % 5; config.operationCount = 50 + textureTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.80f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.05f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.50f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.25f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.30f; std::string name = de::toString(textureTestNdx); texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } textureTests->addChild(texSubImage2DTests); } { TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Texture gen, delete and copyteximage2d tests"); for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + textureTestNdx % 5; config.operationCount = 40 + textureTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.80f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.20f; std::string name = de::toString(textureTestNdx); copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } textureTests->addChild(copyTexImage2DTests); } { TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Texture gen, delete, teximage2D and copytexsubimage2d tests"); for (int textureTestNdx = 0; textureTestNdx < 20; textureTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + textureTestNdx % 5; config.operationCount = 50 + textureTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.80f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.05f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.50f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.30f; std::string name = de::toString(textureTestNdx); copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } textureTests->addChild(copyTexSubImage2DTests); } group->addChild(textureTests); TestCaseGroup* bufferTests = new TestCaseGroup(ctx, "buffers", "Buffer management tests"); { TestCaseGroup* genBufferTests = new TestCaseGroup(ctx, "gen_delete", "Buffer gen and delete tests"); for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + bufferTestNdx % 5; config.operationCount = 30 + bufferTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER] = 0.75f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER] = 0.5f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER] = 0.5f; std::string name = de::toString(bufferTestNdx); genBufferTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } bufferTests->addChild(genBufferTests); } { TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "bufferdata", "Buffer gen, delete and bufferdata tests"); for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + bufferTestNdx % 5; config.operationCount = 40 + bufferTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA] = 0.80f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA] = 0.30f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER] = 0.40f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER] = 0.40f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA] = 0.20f; std::string name = de::toString(bufferTestNdx); texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } bufferTests->addChild(texImage2DTests); } { TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "buffersubdata", "Buffer gen, delete, bufferdata and bufferdata tests"); for (int bufferTestNdx = 0; bufferTestNdx < 20; bufferTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + bufferTestNdx % 5; config.operationCount = 50 + bufferTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_BUFFER] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_DESTROY_BUFFER] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_CREATE_BUFFER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_DATA] = 0.80f; config.probabilities[THREADOPERATIONID_CREATE_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA] = 0.05f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_DESTROY_BUFFER] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_CREATE_BUFFER] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_DATA] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_BUFFER][THREADOPERATIONID_BUFFER_SUBDATA] = 0.10f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_DESTROY_BUFFER] = 0.20f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_CREATE_BUFFER] = 0.20f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_DATA] = 0.10f; config.probabilities[THREADOPERATIONID_BUFFER_DATA][THREADOPERATIONID_BUFFER_SUBDATA] = 0.50f; config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_DESTROY_BUFFER] = 0.20f; config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_CREATE_BUFFER] = 0.25f; config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_DATA] = 0.25f; config.probabilities[THREADOPERATIONID_BUFFER_SUBDATA][THREADOPERATIONID_BUFFER_SUBDATA] = 0.30f; std::string name = de::toString(bufferTestNdx); texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } bufferTests->addChild(texSubImage2DTests); } group->addChild(bufferTests); TestCaseGroup* shaderTests = new TestCaseGroup(ctx, "shaders", "Shader management tests"); { TestCaseGroup* createShaderTests = new TestCaseGroup(ctx, "create_destroy", "Shader create and destroy tests"); for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + shaderTestNdx % 5; config.operationCount = 30 + shaderTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.40f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.40f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.40f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.25f; std::string name = de::toString(shaderTestNdx); createShaderTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } shaderTests->addChild(createShaderTests); } { TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "source", "Shader create, destroy and source tests"); for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + shaderTestNdx % 5; config.operationCount = 40 + shaderTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.50f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.50f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE] = 0.40f; std::string name = de::toString(shaderTestNdx); texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } shaderTests->addChild(texImage2DTests); } { TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "compile", "Shader create, destroy, source and compile tests"); for (int shaderTestNdx = 0; shaderTestNdx < 20; shaderTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + shaderTestNdx % 5; config.operationCount = 50 + shaderTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.5f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.50f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.50f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE] = 0.50f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE] = 0.30f; std::string name = de::toString(shaderTestNdx); texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } shaderTests->addChild(texSubImage2DTests); } group->addChild(shaderTests); TestCaseGroup* programTests = new TestCaseGroup(ctx, "programs", "Program management tests"); { TestCaseGroup* createProgramTests = new TestCaseGroup(ctx, "create_destroy", "Program create and destroy tests"); for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + programTestNdx % 5; config.operationCount = 30 + programTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.75f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.5f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.5f; std::string name = de::toString(programTestNdx); createProgramTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } programTests->addChild(createProgramTests); } { TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "attach_detach", "Program create, destroy, attach and detach tests"); for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + programTestNdx % 5; config.operationCount = 60 + programTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.35f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.35f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE] = 0.50f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER] = 0.25f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE] = 0.30f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER] = 0.35f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.30f; std::string name = de::toString(programTestNdx); texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } programTests->addChild(texImage2DTests); } { TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "link", "Program create, destroy, attach and link tests"); for (int programTestNdx = 0; programTestNdx < 20; programTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + programTestNdx % 5; config.operationCount = 70 + programTestNdx; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.35f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.35f; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_PROGRAM] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_VERTEX_SHADER][THREADOPERATIONID_LINK_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_FRAGMENT_SHADER][THREADOPERATIONID_LINK_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_SHADER][THREADOPERATIONID_LINK_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_SOURCE] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_SHADER_COMPILE] = 0.50f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_DESTROY_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_ATTACH_SHADER] = 0.25f; config.probabilities[THREADOPERATIONID_SHADER_SOURCE][THREADOPERATIONID_LINK_PROGRAM] = 0.20f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.15f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_SOURCE] = 0.30f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_SHADER_COMPILE] = 0.30f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_CREATE_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_DESTROY_PROGRAM] = 0.10f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_ATTACH_SHADER] = 0.35f; config.probabilities[THREADOPERATIONID_SHADER_COMPILE][THREADOPERATIONID_LINK_PROGRAM] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_SOURCE] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_SHADER_COMPILE] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_ATTACH_SHADER] = 0.40f; config.probabilities[THREADOPERATIONID_CREATE_PROGRAM][THREADOPERATIONID_LINK_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_ATTACH_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_PROGRAM][THREADOPERATIONID_LINK_PROGRAM] = 0.05f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_CREATE_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_ATTACH_SHADER] = 0.30f; config.probabilities[THREADOPERATIONID_ATTACH_SHADER][THREADOPERATIONID_LINK_PROGRAM] = 0.30f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_VERTEX_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_FRAGMENT_SHADER] = 0.20f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_SOURCE] = 0.10f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_SHADER_COMPILE] = 0.10f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_CREATE_PROGRAM] = 0.20f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_DESTROY_PROGRAM] = 0.15f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_ATTACH_SHADER] = 0.10f; config.probabilities[THREADOPERATIONID_LINK_PROGRAM][THREADOPERATIONID_LINK_PROGRAM] = 0.05f; std::string name = de::toString(programTestNdx); texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } programTests->addChild(texSubImage2DTests); } group->addChild(programTests); TestCaseGroup* imageTests = new TestCaseGroup(ctx, "images", "Image management tests"); { TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "create_destroy", "Image gen, delete and teximage2D tests"); for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + imageTestNdx % 5; config.operationCount = 70 + imageTestNdx; config.useImages = true; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.35f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.35f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.35f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.35f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.40f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.35f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.30f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; std::string name = de::toString(imageTestNdx); texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } imageTests->addChild(texImage2DTests); } { TestCaseGroup* texImage2DTests = new TestCaseGroup(ctx, "teximage2d", "Image gen, delete and teximage2D tests"); for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + imageTestNdx % 5; config.operationCount = 70 + imageTestNdx; config.useImages = true; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; std::string name = de::toString(imageTestNdx); texImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } imageTests->addChild(texImage2DTests); } { TestCaseGroup* texSubImage2DTests = new TestCaseGroup(ctx, "texsubimage2d", "Image gen, delete, teximage2D and texsubimage2d tests"); for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + imageTestNdx % 5; config.operationCount = 70 + imageTestNdx; config.useImages = true; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXSUBIMAGE2D][THREADOPERATIONID_TEXSUBIMAGE2D] = 0.10f; std::string name = de::toString(imageTestNdx); texSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } imageTests->addChild(texSubImage2DTests); } { TestCaseGroup* copyTexImage2DTests = new TestCaseGroup(ctx, "copyteximage2d", "Image gen, delete and copyteximage2d tests"); for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + imageTestNdx % 5; config.operationCount = 70 + imageTestNdx; config.useImages = true; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_COPYTEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; std::string name = de::toString(imageTestNdx); copyTexImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } imageTests->addChild(copyTexImage2DTests); } { TestCaseGroup* copyTexSubImage2DTests = new TestCaseGroup(ctx, "copytexsubimage2d", "Image gen, delete, teximage2D and copytexsubimage2d tests"); for (int imageTestNdx = 0; imageTestNdx < 20; imageTestNdx++) { GLES2SharingRandomTest::TestConfig config; config.useFenceSync = useSync; config.serverSync = serverSync; config.threadCount = 2 + imageTestNdx % 5; config.operationCount = 70 + imageTestNdx; config.useImages = true; config.probabilities[THREADOPERATIONID_NONE][THREADOPERATIONID_CREATE_TEXTURE] = 1.0f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.30f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.20f; config.probabilities[THREADOPERATIONID_CREATE_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.20f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_DESTROY_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_TEXTURE_FROM_IMAGE][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_CREATE_IMAGE_FROM_TEXTURE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_DESTROY_IMAGE] = 0.25f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXIMAGE2D] = 0.15f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_TEXTURE_FROM_IMAGE] = 0.15f; config.probabilities[THREADOPERATIONID_COPYTEXSUBIMAGE2D][THREADOPERATIONID_COPYTEXSUBIMAGE2D] = 0.10f; std::string name = de::toString(imageTestNdx); copyTexSubImage2DTests->addChild(new GLES2SharingRandomTest(ctx, config, name.c_str(), name.c_str())); } imageTests->addChild(copyTexSubImage2DTests); } group->addChild(imageTests); } } GLES2SharingThreadedTests::GLES2SharingThreadedTests (EglTestContext& eglTestCtx) : TestCaseGroup(eglTestCtx, "multithread", "EGL GLES2 sharing multithread tests") { } void GLES2SharingThreadedTests::init (void) { tcu::TestCaseGroup* simpleTests = new TestCaseGroup(m_eglTestCtx, "simple", "Simple multithreaded tests"); addSimpleTests(m_eglTestCtx, simpleTests, false, false); addChild(simpleTests); TestCaseGroup* randomTests = new TestCaseGroup(m_eglTestCtx, "random", "Random tests"); addRandomTests(m_eglTestCtx, randomTests, false, false); addChild(randomTests); tcu::TestCaseGroup* simpleTestsSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_sync", "Simple multithreaded tests with EGL_KHR_fence_sync"); addSimpleTests(m_eglTestCtx, simpleTestsSync, true, false); addChild(simpleTestsSync); TestCaseGroup* randomTestsSync = new TestCaseGroup(m_eglTestCtx, "random_egl_sync", "Random tests with EGL_KHR_fence_sync"); addRandomTests(m_eglTestCtx, randomTestsSync, true, false); addChild(randomTestsSync); tcu::TestCaseGroup* simpleTestsServerSync = new TestCaseGroup(m_eglTestCtx, "simple_egl_server_sync", "Simple multithreaded tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync"); addSimpleTests(m_eglTestCtx, simpleTestsServerSync, true, true); addChild(simpleTestsServerSync); TestCaseGroup* randomTestsServerSync = new TestCaseGroup(m_eglTestCtx, "random_egl_server_sync", "Random tests with EGL_KHR_fence_sync and EGL_KHR_wait_sync"); addRandomTests(m_eglTestCtx, randomTestsServerSync, true, true); addChild(randomTestsServerSync); } } // egl } // deqp