Added LogVisor

This commit is contained in:
Jack Andersen 2015-10-29 20:26:02 -10:00
parent 2814da014f
commit b73ecde4aa
12 changed files with 277 additions and 81 deletions

3
.gitmodules vendored
View File

@ -0,0 +1,3 @@
[submodule "LogVisor"]
path = LogVisor
url = https://github.com/AxioDL/LogVisor.git

View File

@ -5,6 +5,12 @@ if (NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
endif()
if (NOT TARGET LogVisor)
add_subdirectory(LogVisor)
set(LOG_VISOR_INCLUDE_DIR LogVisor/include)
endif()
include_directories(include ${LOG_VISOR_INCLUDE_DIR})
if(WIN32)
list(APPEND PLAT_SRCS
lib/win/ApplicationWin32.cpp

1
LogVisor Submodule

@ -0,0 +1 @@
Subproject commit 189e047977b138b711259ad84d94471f5d006ffb

View File

@ -5,6 +5,8 @@
namespace boo
{
struct IGraphicsCommandQueue;
struct IGraphicsDataFactory;
class IWindowCallback
{
@ -147,6 +149,12 @@ public:
};
virtual ETouchType getTouchType() const=0;
virtual IGraphicsCommandQueue* getCommandQueue()=0;
virtual IGraphicsDataFactory* getDataFactory()=0;
/* Creates a new context on current thread!! Call from client loading thread */
virtual IGraphicsDataFactory* getLoadContextDataFactory()=0;
};
}

View File

@ -5,6 +5,11 @@
namespace boo
{
enum Primitive
{
PrimitiveTriangles,
PrimitiveTriStrips
};
struct IGraphicsCommandQueue
{
@ -20,11 +25,6 @@ struct IGraphicsCommandQueue
virtual void setClearColor(const float rgba[4])=0;
virtual void clearTarget(bool render=true, bool depth=true)=0;
enum Primitive
{
PrimitiveTriangles,
TrimitiveTriStrips
};
virtual void setDrawPrimitive(Primitive prim)=0;
virtual void draw(size_t start, size_t count)=0;
virtual void drawIndexed(size_t start, size_t count)=0;

View File

@ -35,6 +35,15 @@ protected:
IGraphicsBufferD() : IGraphicsBuffer(true) {}
};
/** Supported buffer uses */
enum BufferUse
{
BufferUseNull,
BufferUseVertex,
BufferUseIndex,
BufferUseUniform
};
struct ITexture
{
bool dynamic() const {return m_dynamic;}
@ -61,11 +70,37 @@ protected:
ITextureD() : ITexture(true) {}
};
/** Supported texture formats */
enum TextureFormat
{
TextureFormatRGBA8,
TextureFormatDXT1,
TextureFormatPVRTC4
};
/** Opaque token for representing the data layout of a vertex
* in a VBO. Also able to reference buffers for platforms like
* OpenGL that cache object refs */
struct IVertexFormat {};
/** Types of vertex attributes */
enum VertexSemantic
{
VertexSemanticPosition,
VertexSemanticNormal,
VertexSemanticColor,
VertexSemanticUV,
VertexSemanticWeight
};
/** Used to create IVertexFormat */
struct VertexElementDescriptor
{
const IGraphicsBuffer* vertBuffer = nullptr;
const IGraphicsBuffer* indexBuffer = nullptr;
VertexSemantic semantic;
};
/** Opaque token for referencing a complete graphics pipeline state necessary
* to rasterize geometry (shaders and blending modes mainly) */
struct IShaderPipeline {};
@ -83,6 +118,21 @@ struct IGraphicsData
virtual ~IGraphicsData() {}
};
/** Used by platform shader pipeline constructors */
enum BlendFactor
{
BlendFactorZero,
BlendFactorOne,
BlendFactorSrcColor,
BlendFactorInvSrcColor,
BlendFactorDstColor,
BlendFactorInvDstColor,
BlendFactorSrcAlpha,
BlendFactorInvSrcAlpha,
BlendFactorDstAlpha,
BlendFactorInvDstAlpha
};
/** Factory object for creating batches of resources as an IGraphicsData token */
struct IGraphicsDataFactory
{
@ -101,60 +151,20 @@ struct IGraphicsDataFactory
virtual Platform platform() const=0;
virtual const char* platformName() const=0;
enum BufferUse
{
BufferUseNull,
BufferUseVertex,
BufferUseIndex,
BufferUseUniform
};
virtual const IGraphicsBufferS*
newStaticBuffer(BufferUse use, const void* data, size_t sz)=0;
virtual IGraphicsBufferD*
newDynamicBuffer(BufferUse use)=0;
enum TextureFormat
{
TextureFormatRGBA8,
TextureFormatDXT1,
TextureFormatPVRTC4
};
virtual const ITextureS*
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz)=0;
virtual ITextureD*
newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0;
struct VertexElementDescriptor
{
const IGraphicsBuffer* vertBuffer = nullptr;
const IGraphicsBuffer* indexBuffer = nullptr;
enum VertexSemantic
{
VertexSemanticPosition,
VertexSemanticNormal,
VertexSemanticColor,
VertexSemanticUV,
VertexSemanticWeight
} semantic;
};
virtual const IVertexFormat*
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0;
enum BlendFactor
{
BlendFactorZero,
BlendFactorOne,
BlendFactorSrcColor,
BlendFactorInvSrcColor,
BlendFactorDstColor,
BlendFactorInvDstColor,
BlendFactorSrcAlpha,
BlendFactorInvSrcAlpha,
BlendFactorDstAlpha,
BlendFactorInvDstAlpha
};
virtual const IShaderDataBinding*
newShaderDataBinding(const IShaderPipeline* pipeline,
const IVertexFormat* vtxFormat,

View File

@ -1,14 +1,16 @@
#include "boo/graphicsdev/GLES3.hpp"
#include "boo/IGraphicsContext.hpp"
#include <GLES3/gl3ext.h>
#include <stdio.h>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <LogVisor/LogVisor.hpp>
namespace boo
{
static LogVisor::LogModule Log("boo::GLES3");
struct GLES3Data : IGraphicsData
{
@ -35,7 +37,7 @@ class GLES3GraphicsBufferS : IGraphicsBufferS
friend struct GLES3CommandQueue;
GLuint m_buf;
GLenum m_target;
GLES3GraphicsBufferS(IGraphicsDataFactory::BufferUse use, const void* data, size_t sz)
GLES3GraphicsBufferS(BufferUse use, const void* data, size_t sz)
{
m_target = USE_TABLE[use];
glGenBuffers(1, &m_buf);
@ -62,7 +64,7 @@ class GLES3GraphicsBufferD : IGraphicsBufferD
GLenum m_target;
void* m_mappedBuf = nullptr;
size_t m_mappedSize = 0;
GLES3GraphicsBufferD(GLES3CommandQueue* q, IGraphicsDataFactory::BufferUse use)
GLES3GraphicsBufferD(GLES3CommandQueue* q, BufferUse use)
: m_q(q)
{
m_target = USE_TABLE[use];
@ -93,13 +95,12 @@ class GLES3TextureS : ITextureS
friend class GLES3DataFactory;
GLuint m_tex;
GLES3TextureS(size_t width, size_t height, size_t mips,
IGraphicsDataFactory::TextureFormat fmt,
const void* data, size_t sz)
TextureFormat fmt, const void* data, size_t sz)
{
const uint8_t* dataIt = static_cast<const uint8_t*>(data);
glGenTextures(1, &m_tex);
glBindTexture(GL_TEXTURE_2D, m_tex);
if (fmt == IGraphicsDataFactory::TextureFormatRGBA8)
if (fmt == TextureFormatRGBA8)
{
for (size_t i=0 ; i<mips ; ++i)
{
@ -131,8 +132,7 @@ class GLES3TextureD : ITextureD
size_t m_mappedSize = 0;
size_t m_width = 0;
size_t m_height = 0;
GLES3TextureD(GLES3CommandQueue* q, size_t width, size_t height,
IGraphicsDataFactory::TextureFormat fmt);
GLES3TextureD(GLES3CommandQueue* q, size_t width, size_t height, TextureFormat fmt);
public:
~GLES3TextureD();
@ -281,7 +281,7 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline
GLES3ShaderPipeline shader;
if (!shader.initObjects())
{
fprintf(stderr, "unable to create shader objects\n");
Log.report(LogVisor::Error, "unable to create shader objects\n");
return nullptr;
}
shader.m_sfactor = BLEND_FACTOR_TABLE[srcFac];
@ -300,7 +300,7 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline
glGetShaderiv(shader.m_vert, GL_INFO_LOG_LENGTH, &logLen);
char* log = (char*)malloc(logLen);
glGetShaderInfoLog(shader.m_vert, logLen, nullptr, log);
fprintf(stderr, "unable to compile vert source\n%s\n%s\n", log, vertSource);
Log.report(LogVisor::Error, "unable to compile vert source\n%s\n%s\n", log, vertSource);
free(log);
return nullptr;
}
@ -314,7 +314,7 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline
glGetShaderiv(shader.m_frag, GL_INFO_LOG_LENGTH, &logLen);
char* log = (char*)malloc(logLen);
glGetShaderInfoLog(shader.m_frag, logLen, nullptr, log);
fprintf(stderr, "unable to compile frag source\n%s\n%s\n", log, fragSource);
Log.report(LogVisor::Error, "unable to compile frag source\n%s\n%s\n", log, fragSource);
free(log);
return nullptr;
}
@ -327,7 +327,7 @@ const IShaderPipeline* GLES3DataFactory::newShaderPipeline
glGetProgramiv(shader.m_prog, GL_INFO_LOG_LENGTH, &logLen);
char* log = (char*)malloc(logLen);
glGetProgramInfoLog(shader.m_prog, logLen, nullptr, log);
fprintf(stderr, "unable to link shader program\n%s\n", log);
Log.report(LogVisor::Error, "unable to link shader program\n%s\n", log);
free(log);
return nullptr;
}
@ -342,9 +342,9 @@ struct GLES3VertexFormat : IVertexFormat
GLES3CommandQueue* m_q;
GLuint m_vao = 0;
size_t m_elementCount;
std::unique_ptr<GLES3DataFactory::VertexElementDescriptor[]> m_elements;
std::unique_ptr<VertexElementDescriptor[]> m_elements;
GLES3VertexFormat(GLES3CommandQueue* q, size_t elementCount,
const GLES3DataFactory::VertexElementDescriptor* elements);
const VertexElementDescriptor* elements);
~GLES3VertexFormat();
void bind() const {glBindVertexArray(m_vao);}
};
@ -468,7 +468,7 @@ struct GLES3CommandQueue : IGraphicsCommandQueue
const ITextureD* target;
float rgba[4];
GLbitfield flags;
Primitive prim;
GLenum prim;
struct
{
size_t start;
@ -500,7 +500,7 @@ struct GLES3CommandQueue : IGraphicsCommandQueue
size_t stride = 0;
for (size_t i=0 ; i<fmt->m_elementCount ; ++i)
{
const IGraphicsDataFactory::VertexElementDescriptor* desc = &fmt->m_elements[i];
const VertexElementDescriptor* desc = &fmt->m_elements[i];
stride += SEMANTIC_SIZE_TABLE[desc->semantic];
}
@ -510,7 +510,7 @@ struct GLES3CommandQueue : IGraphicsCommandQueue
const IGraphicsBuffer* lastEBO = nullptr;
for (size_t i=0 ; i<fmt->m_elementCount ; ++i)
{
const IGraphicsDataFactory::VertexElementDescriptor* desc = &fmt->m_elements[i];
const VertexElementDescriptor* desc = &fmt->m_elements[i];
if (desc->vertBuffer != lastVBO)
{
lastVBO = desc->vertBuffer;
@ -589,10 +589,7 @@ struct GLES3CommandQueue : IGraphicsCommandQueue
glClear(cmd.flags);
break;
case Command::OpSetDrawPrimitive:
if (cmd.prim == PrimitiveTriangles)
prim = GL_TRIANGLES;
else if (cmd.prim == TrimitiveTriStrips)
prim = GL_TRIANGLE_STRIP;
prim = cmd.prim;
break;
case Command::OpDraw:
glDrawArrays(prim, cmd.start, cmd.count);
@ -661,7 +658,10 @@ struct GLES3CommandQueue : IGraphicsCommandQueue
{
std::vector<Command>& cmds = m_cmdBufs[m_fillBuf];
cmds.emplace_back(Command::OpSetDrawPrimitive);
cmds.back().prim = prim;
if (prim == PrimitiveTriangles)
cmds.back().prim = GL_TRIANGLES;
else if (prim == PrimitiveTriStrips)
cmds.back().prim = GL_TRIANGLE_STRIP;
}
void draw(size_t start, size_t count)
{
@ -772,8 +772,7 @@ GLES3DataFactory::newDynamicBuffer(BufferUse use)
return retval;
}
GLES3TextureD::GLES3TextureD(GLES3CommandQueue* q, size_t width, size_t height,
IGraphicsDataFactory::TextureFormat fmt)
GLES3TextureD::GLES3TextureD(GLES3CommandQueue* q, size_t width, size_t height, TextureFormat fmt)
: m_q(q)
{
m_width = width;
@ -797,10 +796,10 @@ GLES3DataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat f
}
GLES3VertexFormat::GLES3VertexFormat(GLES3CommandQueue* q, size_t elementCount,
const GLES3DataFactory::VertexElementDescriptor* elements)
const VertexElementDescriptor* elements)
: m_q(q),
m_elementCount(elementCount),
m_elements(new GLES3DataFactory::VertexElementDescriptor[elementCount])
m_elements(new VertexElementDescriptor[elementCount])
{
for (size_t i=0 ; i<elementCount ; ++i)
m_elements[i] = elements[i];

View File

@ -123,7 +123,8 @@ static xcb_window_t GetWindowOfEvent(xcb_generic_event_t* event, bool& windowEve
return 0;
}
IWindow* _WindowXCBNew(const std::string& title, xcb_connection_t* conn);
IWindow* _WindowXCBNew(const std::string& title, xcb_connection_t* conn,
xcb_glx_context_t lastCtx);
class ApplicationXCB final : public IApplication
{
@ -341,10 +342,18 @@ public:
std::unique_ptr<IWindow> newWindow(const std::string& title)
{
IWindow* newWindow = _WindowXCBNew(title, m_xcbConn);
IWindow* newWindow = _WindowXCBNew(title, m_xcbConn, m_lastGlxCtx);
m_windows[(xcb_window_t)newWindow->getPlatformHandle()] = newWindow;
return std::unique_ptr<IWindow>(newWindow);
}
/* Last GLX context */
xcb_glx_context_t m_lastGlxCtx = 0;
};
void _XCBUpdateLastGlxCtx(xcb_glx_context_t lastGlxCtx)
{
static_cast<ApplicationXCB*>(APP)->m_lastGlxCtx = lastGlxCtx;
}
}

View File

@ -63,11 +63,29 @@ public:
{
}
IGraphicsCommandQueue* getCommandQueue()
{
return nullptr;
}
IGraphicsDataFactory* getDataFactory()
{
return nullptr;
}
IGraphicsDataFactory* getLoadContextDataFactory()
{
return nullptr;
}
};
struct WindowWayland : IWindow
{
GraphicsContextWayland m_gfxCtx;
WindowWayland(const std::string& title)
: m_gfxCtx(IGraphicsContext::API_OPENGL_3_3, this)
{
}
@ -149,6 +167,22 @@ struct WindowWayland : IWindow
}
IGraphicsCommandQueue* getCommandQueue()
{
return m_gfxCtx.getCommandQueue();
}
IGraphicsDataFactory* getDataFactory()
{
return m_gfxCtx.getDataFactory();
}
IGraphicsDataFactory* getLoadContextDataFactory()
{
return m_gfxCtx.getLoadContextDataFactory();
}
};
IWindow* _WindowWaylandNew(const std::string& title)

View File

@ -29,6 +29,7 @@
namespace boo
{
IGraphicsCommandQueue* _NewGLES3CommandQueue(IGraphicsContext* parent);
void _XCBUpdateLastGlxCtx(xcb_glx_context_t lastGlxCtx);
extern PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI;
extern PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI;
@ -161,6 +162,7 @@ struct GraphicsContextXCB : IGraphicsContext
EPixelFormat m_pf;
IWindow* m_parentWindow;
xcb_connection_t* m_xcbConn;
xcb_glx_context_t m_lastCtx = 0;
xcb_glx_fbconfig_t m_fbconfig = 0;
xcb_visualid_t m_visualid = 0;
@ -289,7 +291,8 @@ public:
m_parentWindow->getPlatformHandle(),
m_glxWindow, 0, NULL);
m_glxCtx = xcb_generate_id(m_xcbConn);
xcb_glx_create_context(m_xcbConn, m_glxCtx, m_visualid, 0, 0, 1);
xcb_glx_create_context(m_xcbConn, m_glxCtx, m_visualid, 0, m_lastCtx, 1);
_XCBUpdateLastGlxCtx(m_glxCtx);
}
void makeCurrent()
@ -357,7 +360,7 @@ struct WindowXCB : IWindow
public:
WindowXCB(const std::string& title, xcb_connection_t* conn)
WindowXCB(const std::string& title, xcb_connection_t* conn, xcb_glx_context_t lastCtx)
: m_xcbConn(conn), m_callback(NULL), m_gfxCtx(IGraphicsContext::API_OPENGL_3_3, this, m_xcbConn, m_visualId)
{
if (!S_ATOMS)
@ -952,11 +955,27 @@ public:
return m_touchType;
}
IGraphicsCommandQueue* getCommandQueue()
{
return m_gfxCtx.getCommandQueue();
}
IGraphicsDataFactory* getDataFactory()
{
return m_gfxCtx.getDataFactory();
}
IGraphicsDataFactory* getLoadContextDataFactory()
{
return m_gfxCtx.getLoadContextDataFactory();
}
};
IWindow* _WindowXCBNew(const std::string& title, xcb_connection_t* conn)
IWindow* _WindowXCBNew(const std::string& title, xcb_connection_t* conn,
xcb_glx_context_t lastCtx)
{
return new WindowXCB(title, conn);
return new WindowXCB(title, conn, lastCtx);
}
}

View File

@ -1,2 +1,2 @@
add_executable(booTest main.cpp)
target_link_libraries(booTest Boo ${BOO_SYS_LIBS})
target_link_libraries(booTest Boo LogVisor ${BOO_SYS_LIBS})

View File

@ -1,5 +1,9 @@
#include <stdio.h>
#include <boo/boo.hpp>
#include <boo/graphicsdev/GLES3.hpp>
#include <thread>
#include <mutex>
#include <condition_variable>
namespace boo
{
@ -166,13 +170,104 @@ struct CTestWindowCallback : IWindowCallback
};
struct TestApplicationCallback : IApplicationCallback
{
std::unique_ptr<IWindow> mainWindow;
boo::TestDeviceFinder devFinder;
CTestWindowCallback windowCallback;
bool running = true;
const IShaderDataBinding* m_binding = nullptr;
std::mutex m_mt;
std::condition_variable m_cv;
static void LoaderProc(TestApplicationCallback* self)
{
GLES3DataFactory* factory =
dynamic_cast<GLES3DataFactory*>(self->mainWindow->getLoadContextDataFactory());
/* Make Tri-strip VBO */
struct Vert
{
float pos[3];
float uv[2];
};
static const Vert quad[4] =
{
{{1.0,1.0},{1.0,1.0}},
{{-1.0,1.0},{0.0,1.0}},
{{1.0,-1.0},{1.0,0.0}},
{{-1.0,-1.0},{0.0,0.0}}
};
const IGraphicsBuffer* vbo =
factory->newStaticBuffer(BufferUseVertex, quad, sizeof(quad));
/* Make vertex format */
const VertexElementDescriptor descs[2] =
{
{vbo, nullptr, VertexSemanticPosition},
{vbo, nullptr, VertexSemanticUV}
};
const IVertexFormat* vfmt = factory->newVertexFormat(2, descs);
/* Make ramp texture */
using Pixel = uint8_t[4];
static Pixel tex[256][256];
for (int i=0 ; i<256 ; ++i)
for (int j=0 ; j<256 ; ++j)
{
tex[i][j][0] = i;
tex[i][j][1] = j;
tex[i][j][2] = 0;
tex[i][j][3] = 0xff;
}
const ITexture* texture =
factory->newStaticTexture(256, 256, 1, TextureFormatRGBA8, tex, 256*256*4);
/* Make shader pipeline */
static const char* VS =
"#version 300\n"
"layout(location=0) in vec3 in_pos;\n"
"layout(location=1) in vec2 in_uv;\n"
"out vec2 out_uv;\n"
"void main()\n"
"{\n"
" gl_Position = in_pos;\n"
" out_uv = in_uv;\n"
"}\n";
static const char* FS =
"#version 300\n"
"layout(binding=0) uniform sampler2D tex;\n"
"layout(location=0) out vec4 out_frag;\n"
"in vec2 out_uv;\n"
"void main()\n"
"{\n"
" out_frag = texture(tex, out_uv);\n"
"}\n";
const IShaderPipeline* pipeline =
factory->newShaderPipeline(VS, FS, BlendFactorOne, BlendFactorZero, true, true, false);
/* Make shader data binding */
self->m_binding =
factory->newShaderDataBinding(pipeline, vfmt, vbo, nullptr, 0, nullptr, 1, &texture);
/* Commit objects */
std::unique_ptr<IGraphicsData> data = factory->commit();
/* Wait for exit */
while (self->running)
{
{
std::unique_lock<std::mutex> lk(self->m_mt);
self->m_cv.wait(lk);
if (!self->running)
break;
}
}
}
int appMain(IApplication* app)
{
mainWindow = app->newWindow(_S("YAY!"));
@ -180,13 +275,25 @@ struct TestApplicationCallback : IApplicationCallback
mainWindow->showWindow();
devFinder.startScanning();
IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue();
std::thread loaderThread(LoaderProc, this);
size_t retraceCount = 0;
while (running)
{
retraceCount = mainWindow->waitForRetrace(retraceCount);
if (m_binding)
{
gfxQ->setDrawPrimitive(PrimitiveTriStrips);
gfxQ->clearTarget();
gfxQ->setShaderDataBinding(m_binding);
gfxQ->draw(0, 4);
gfxQ->execute();
}
}
m_cv.notify_one();
loaderThread.join();
return 0;
}
void appQuitting(IApplication*)