UNSET(ENABLE_VALIDATION CACHE)
UNSET(ENABLE_WIRED_FILL CACHE)
ENDIF()
-
+OPTION(VKVG_TEST_DIRECT_DRAW "Draw directly on backend surface, if off surface is blitted." ON)
+IF (VKVG_TEST_DIRECT_DRAW)
+ ADD_DEFINITIONS (-DVKVG_TEST_DIRECT_DRAW)
+ENDIF ()
OPTION(VKVG_PREMULT_ALPHA "use premultiplied alpha for internal rendering" ON)
IF (VKVG_PREMULT_ALPHA)
ADD_DEFINITIONS (-DVKVG_PREMULT_ALPHA)
### To Do
-- [ ] Use Scissor where possible.
-- [ ] Improve stroke algorithms.
+- [x] Use Scissor where possible.
+- [x] Improve stroke algorithms.
- [ ] Radial gradients.
- [ ] Dashed lines.
- [ ] Operators.
- [x] Optimize vulkan memory allocations by sub-allocating from a single shared memory chunk per type.
-- [ ] Optimize command submissions.
+- [x] Optimize command submissions.
- [x] Test SDF font rendering.
- [x] Avoid line joins inside curves and arc.
- [ ] Structured unit testing.
ctx->pSurf->new = false;
- ctx->renderPassBeginInfo.clearValueCount = 3;
+ if (dev->samples == VK_SAMPLE_COUNT_1_BIT)
+ ctx->renderPassBeginInfo.clearValueCount = 2;
+ else
+ ctx->renderPassBeginInfo.clearValueCount = 3;
- ctx->pPrev = surf->dev->lastCtx;
+ ctx->pPrev = surf->dev->lastCtx;
if (ctx->pPrev != NULL)
ctx->pPrev->pNext = ctx;
surf->dev->lastCtx = ctx;
*/
void vkvg_flush (VkvgContext ctx){
_flush_cmd_buff(ctx);
- _wait_flush_fence(ctx);
+ //_wait_flush_fence(ctx);
/*
#ifdef DEBUG
iR = ctx->pathes[ptrPath]&PATH_ELT_MASK;
_build_vb_step(ctx,v,hw,iL,i,iR, false);
- uint32_t* inds = &ctx->indexCache [ctx->indCount-6];
- uint32_t ii = firstIdx;
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount-6];
+ VKVG_IBO_INDEX_TYPE ii = firstIdx;
inds[1] = ii;
inds[4] = ii;
inds[5] = ii+1;
else if (ctx->pushCstDirty)
_update_push_constants(ctx);
}
+void _check_vbo_size (VkvgContext ctx) {
+ if (ctx->sizeVertices - ctx->vertCount > VKVG_ARRAY_THRESHOLD)
+ return;
+ ctx->sizeVertices += VKVG_VBO_SIZE;
+ ctx->vertexCache = (Vertex*) realloc (ctx->vertexCache, ctx->sizeVertices * sizeof(Vertex));
+}
+void _check_ibo_size (VkvgContext ctx) {
+ if (ctx->sizeIndices - ctx->indCount > VKVG_ARRAY_THRESHOLD)
+ return;
+ ctx->sizeIndices += VKVG_IBO_SIZE;
+ ctx->indexCache = (VKVG_IBO_INDEX_TYPE*) realloc (ctx->vertexCache, ctx->sizeVertices * sizeof(VKVG_IBO_INDEX_TYPE));
+}
void _check_pathes_array (VkvgContext ctx){
if (ctx->sizePathes - ctx->pathPtr - ctx->curvePtr > VKVG_ARRAY_THRESHOLD)
return;
ctx->sizePathes += VKVG_PATHES_SIZE;
- ctx->pathes = (uint32_t*) realloc (ctx->pathes, ctx->sizePathes*sizeof(uint32_t));
+ ctx->pathes = (uint32_t*) realloc (ctx->pathes, ctx->sizePathes * sizeof(uint32_t));
}
//when empty, ptr is even, else it's odd
//when empty, no current point is defined.
void _create_vertices_buff (VkvgContext ctx){
ctx->vertexCache = (Vertex*)malloc(ctx->sizeVertices * sizeof(Vertex));
- ctx->indexCache = (uint32_t*)malloc(ctx->sizeVertices * sizeof(uint32_t));
+ ctx->indexCache = (VKVG_IBO_INDEX_TYPE*)malloc(ctx->sizeVertices * sizeof(VKVG_IBO_INDEX_TYPE));
vkvg_buffer_create (ctx->pSurf->dev,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
vkvg_buffer_create (ctx->pSurf->dev,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VMA_MEMORY_USAGE_CPU_TO_GPU,
- ctx->sizeIndices * sizeof(uint32_t), &ctx->indices);
+ ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE), &ctx->indices);
}
const vec3 blankuv = {};
void _add_vertexf (VkvgContext ctx, float x, float y){
ctx->vertexCache[idx] = v;
}
void _add_tri_indices_for_rect (VkvgContext ctx, uint32_t i){
- uint32_t* inds = &ctx->indexCache[ctx->indCount];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
inds[0] = i;
inds[1] = i+2;
inds[2] = i+1;
ctx->indCount+=6;
}
void _add_triangle_indices(VkvgContext ctx, uint32_t i0, uint32_t i1, uint32_t i2){
- uint32_t* inds = &ctx->indexCache[ctx->indCount];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount];
inds[0] = i0;
inds[1] = i1;
inds[2] = i2;
return;
memcpy(ctx->vertices.allocInfo.pMappedData, ctx->vertexCache, ctx->vertCount * sizeof (Vertex));
- memcpy(ctx->indices.allocInfo.pMappedData, ctx->indexCache, ctx->indCount * sizeof (uint32_t));
+ memcpy(ctx->indices.allocInfo.pMappedData, ctx->indexCache, ctx->indCount * sizeof (VKVG_IBO_INDEX_TYPE));
_end_render_pass (ctx);
vkh_cmd_end (ctx->cmd);
VkDeviceSize offsets[1] = { 0 };
CmdBindVertexBuffers(ctx->cmd, 0, 1, &ctx->vertices.buffer, offsets);
- CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VK_INDEX_TYPE_UINT32);
+ if (sizeof (VKVG_IBO_INDEX_TYPE) == 4)
+ CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VK_INDEX_TYPE_UINT32);
+ else
+ CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VK_INDEX_TYPE_UINT16);
_update_push_constants (ctx);
_add_vertex(ctx, v);
v.pos = p2;
_add_vertex(ctx, v);
- uint32_t* inds = &ctx->indexCache [ctx->indCount];
+ VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount];
inds[0] = ctx->vertCount - 2;
inds[1] = ctx->vertCount - 1;
ctx->indCount+=2;
#define VKVG_IBO_SIZE VKVG_VBO_SIZE * 6
#define VKVG_PATHES_SIZE 16
#define VKVG_ARRAY_THRESHOLD 4
+#define VKVG_IBO_INDEX_TYPE uint16_t
typedef struct{
vec2 pos;
size_t sizeVertices; //reserved size
uint32_t vertCount; //effective vertices count
- Vertex* vertexCache;
- uint32_t* indexCache;
-
+ Vertex* vertexCache;
+ VKVG_IBO_INDEX_TYPE* indexCache;
//pathes, exists until stroke of fill
vec2* points; //points array
bool _current_path_is_empty (VkvgContext ctx);
void _start_sub_path (VkvgContext ctx, float x, float y);
+void _check_vbo_size (VkvgContext ctx);
+void _check_ibo_size (VkvgContext ctx);
void _check_pathes_array (VkvgContext ctx);
void _finish_path (VkvgContext ctx);
void _clear_path (VkvgContext ctx);
return;
vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL);
- vkh_image_destroy(surf->img);
+ if (!surf->img->imported)
+ vkh_image_destroy(surf->img);
+
vkh_image_destroy(surf->imgMS);
vkh_image_destroy(surf->stencil);
-#include "test.h"
+#include "test.h"
float panX = 0.f;
float panY = 0.f;
VkvgDevice device = NULL;
VkvgSurface surf = NULL;
+uint iterations = 250; // items drawn in one run, or complexity
+uint runs = 10; // repeat test n times
+
+static vk_engine_t* e;
+
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action != GLFW_PRESS)
return;
(float)rand()/RAND_MAX
);
}
-static vk_engine_t* e;
void init_test (uint width, uint height){
e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_MAILBOX_KHR, width, height);
vkengine_set_cursor_pos_callback(e, mouse_move_callback);
vkengine_set_scroll_callback(e, scroll_callback);
- bool deferredResolve = false;
+ bool deferredResolve = true;
- device = vkvg_device_create_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0, VK_SAMPLE_COUNT_1_BIT, deferredResolve);
+ device = vkvg_device_create_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0, VK_SAMPLE_COUNT_4_BIT, deferredResolve);
vkvg_device_set_dpy(device, 96, 96);
vkengine_destroy (e);
}
+#ifdef VKVG_TEST_DIRECT_DRAW
+VkvgSurface* surfaces;
+#endif
+
void perform_test (void(*testfunc)(void),uint width, uint height) {
//dumpLayerExts();
vkvg_device_set_dpy(device, 96, 96);
+#ifdef VKVG_TEST_DIRECT_DRAW
+ VkFence* fences = (VkFence*)calloc(r->imgCount, sizeof (VkFence));
+ surfaces = (VkvgSurface*)malloc(r->imgCount * sizeof (VkvgSurface));
+ for (uint i=0; i < r->imgCount;i++)
+ surfaces[i] = vkvg_surface_create_for_VkhImage (device, r->ScBuffers[i]);
+#else
surf = vkvg_surface_create(device, width, height);
-
- //vkvg_surface_clear(surf);
-
vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), width, height);
-
+#endif
struct timeval before , after;
double frameTime = 0, frameTimeAccum = 0, frameCount = 0;
gettimeofday(&before , NULL);
+#ifdef VKVG_TEST_DIRECT_DRAW
+ VkFence fence = vkh_fence_create (e->dev);
+
+ if (!vkh_presenter_acquireNextImage(r, fence)) {
+ for (uint i=0; i < r->imgCount;i++){
+ if (fences[i]!=NULL){
+ vkDestroyFence (e->dev->dev, fences[i], NULL);
+ fences[i] = NULL;
+ }
+ vkvg_surface_destroy(surfaces[i]);
+ surfaces[i] = vkvg_surface_create_for_VkhImage (device, r->ScBuffers[i]);
+ }
+ vkDestroyFence (e->dev->dev, fence, NULL);
+ }else{
+ surf = surfaces[r->currentScBufferIndex];
+ if (fences[r->currentScBufferIndex] != NULL){
+ vkWaitForFences (e->dev->dev, 1, &fences[r->currentScBufferIndex], VK_TRUE, UINT64_MAX);
+ vkDestroyFence (e->dev->dev, fences[r->currentScBufferIndex], NULL);
+ }
+ fences[r->currentScBufferIndex] = fence;
+
+ testfunc();
+
+ if (deferredResolve)
+ vkvg_multisample_surface_resolve(surf);
+
+ VkPresentInfoKHR present = { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .swapchainCount = 1,
+ .pSwapchains = &r->swapChain,
+ .pImageIndices = &r->currentScBufferIndex };
+
+ /* Make sure command buffer is finished before presenting */
+ VK_CHECK_RESULT(vkQueuePresentKHR(r->queue, &present));
+ }
+#else
testfunc();
if (deferredResolve)
vkvg_multisample_surface_resolve(surf);
if (!vkh_presenter_draw (r))
vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), width, height);
+#endif
- vkDeviceWaitIdle(e->dev->dev);
+ //vkDeviceWaitIdle(e->dev->dev);
gettimeofday(&after , NULL);
frameTimeAccum += time_diff(before , after);
frameCount++;
- fflush(stdout);
+ //fflush(stdout);
}
frameTime = frameTimeAccum / frameCount;
vkDeviceWaitIdle(e->dev->dev);
+#ifdef VKVG_TEST_DIRECT_DRAW
+ for (int i=0; i<r->imgCount;i++){
+ vkvg_surface_destroy (surfaces[i]);
+ if (fences[i]!=NULL)
+ vkDestroyFence (e->dev->dev, fences[i], NULL);
+ }
+ free (fences);
+ free (surfaces);
+#else
vkvg_surface_destroy (surf);
+#endif
+
vkvg_device_destroy (device);
vkengine_destroy (e);
#include "vkh_device.h"
#include "vkh_presenter.h"
+#define M_PIF 3.14159265359f /* float pi */
+#define M_PIF_MULT_2 6.28318530718f
+
#ifdef _WIN32 // MSC_VER
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <sys/time.h>
#endif // _WIN32
+extern uint iterations;
+extern uint runs;
+
extern float panX;
extern float panY;
extern float lastX;
VkvgContext ctx = vkvg_create(surf);
//vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx,20);
+ vkvg_set_line_width(ctx,1);
//vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
- for (int i=0; i<250; i++) {
+ for (uint i=0; i<iterations; i++) {
randomize_color(ctx);
- float x1 = trunc( ((float)w*rand())/RAND_MAX );
- float y1 = trunc( ((float)h*rand())/RAND_MAX );
- float v = trunc( ((float)500*rand())/RAND_MAX );
+ float x1 = w*rand()/RAND_MAX;
+ float y1 = h*rand()/RAND_MAX;
+ float v = 500.f*rand()/RAND_MAX;
vkvg_move_to (ctx, x1, y1);
vkvg_line_to (ctx, x1 + v, y1);
void test(){
vkvg_surface_clear(surf);
+
struct timeval currentTime;
gettimeofday(¤tTime, NULL);
-
srand((unsigned) currentTime.tv_usec);
+
const float w = 1024.f;
const float h = 800.f;
VkvgContext ctx = vkvg_create(surf);
//vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx,2);
+ vkvg_set_line_width (ctx,1);
//vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
- vkvg_set_source_rgba(ctx,1.0,0.0,0.0,0.1);
- for (int i=0; i<250; i++) {
+ for (uint i=0; i<iterations; i++) {
randomize_color(ctx);
- float x1 = trunc( ((float)w*rand())/RAND_MAX );
- float y1 = trunc( ((float)h*rand())/RAND_MAX );
- float x2 = trunc( ((float)w*rand())/RAND_MAX ) + 1;
- float y2 = trunc( ((float)h*rand())/RAND_MAX ) + 1;
+
+ float x1 = w*rand()/RAND_MAX;
+ float y1 = h*rand()/RAND_MAX;
+ float x2 = (w*rand()/RAND_MAX) + 1;
+ float y2 = (h*rand()/RAND_MAX) + 1;
vkvg_move_to (ctx, x1, y1);
vkvg_line_to (ctx, x2, y2);
vkvg_stroke (ctx);
+
+ if (i%100==0)
+ vkvg_flush(ctx);
}
vkvg_destroy(ctx);
}
VkvgContext ctx = vkvg_create(surf);
//vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx,2);
+ vkvg_set_line_width(ctx,1);
//vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
randomize_color(ctx);
- for (int i=0; i<250; i++) {
- float x1 = trunc( ((float)w*rand())/RAND_MAX );
- float y1 = trunc( ((float)h*rand())/RAND_MAX );
- float x2 = trunc( ((float)w*rand())/RAND_MAX ) + 1;
- float y2 = trunc( ((float)h*rand())/RAND_MAX ) + 1;
+ for (int i=0; i<iterations; i++) {
+
+ float x1 = w*rand()/RAND_MAX;
+ float y1 = h*rand()/RAND_MAX;
+ float x2 = (w*rand()/RAND_MAX) + 1;
+ float y2 = (h*rand()/RAND_MAX) + 1;
vkvg_move_to (ctx, x1, y1);
vkvg_line_to (ctx, x2, y2);
+
+ if (i%100==0)
+ vkvg_flush(ctx);
}
vkvg_stroke (ctx);
vkvg_destroy(ctx);
--- /dev/null
+#include "test.h"
+
+void test(){
+ vkvg_surface_clear(surf);
+ struct timeval currentTime;
+ gettimeofday(¤tTime, NULL);
+
+ srand((unsigned) currentTime.tv_usec);
+ const float w = 1024.f;
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
+
+ //vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
+
+ for (int i=0; i<iterations; i++) {
+ randomize_color(ctx);
+
+ float x = w*rand()/RAND_MAX;
+ float y = w*rand()/RAND_MAX;
+ float r = 0.1f*w*rand()/RAND_MAX;
+
+ vkvg_arc(ctx, x, y, r, 0, M_PI * 2.f);
+ vkvg_fill(ctx);
+
+ if (i%50==0)
+ vkvg_flush(ctx);
+ }
+ vkvg_destroy(ctx);
+}
+
+int main(int argc, char *argv[]) {
+
+ perform_test (test, 1024, 768);
+
+ return 0;
+}
VkvgContext ctx = vkvg_create(surf);
vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx,2);
+
//vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
- vkvg_set_source_rgba(ctx,1.0,0.0,0.0,0.1);
- for (int i=0; i<250; i++) {
+
+ for (int i=0; i<iterations; i++) {
randomize_color(ctx);
- float x = trunc( (0.5*(float)w*rand())/RAND_MAX );
- float y = trunc( (0.5*(float)w*rand())/RAND_MAX );
- float z = trunc( (0.5*(float)w*rand())/RAND_MAX ) + 1;
- float v = trunc( (0.5*(float)w*rand())/RAND_MAX ) + 1;
-
- vkvg_rectangle(ctx, x+1, y+1, z, v);
- /*vkvg_fill_preserve(ctx);
- randomize_color(ctx);*/
+
+ float x = 0.5f*w*rand()/RAND_MAX;
+ float y = 0.5f*w*rand()/RAND_MAX;
+ float z = 0.5f*w*rand()/RAND_MAX;
+ float v = 0.5f*w*rand()/RAND_MAX;
+
+ vkvg_rectangle(ctx, x, y, z, v);
vkvg_fill(ctx);
- vkvg_stroke(ctx);
+
+ if (i%30==0)
+ vkvg_flush(ctx);
}
vkvg_destroy(ctx);
}
#include "test.h"
void test(){
- vkvg_matrix_t mat;
- vkvg_matrix_init_identity(&mat);
- vkvg_matrix_scale(&mat,zoom,zoom);
- vkvg_matrix_translate(&mat, panX, panY);
-
vkvg_surface_clear(surf);
VkvgContext ctx = vkvg_create(surf);
- vkvg_set_source_rgba(ctx,1.0f,1.0f,1.0f,1);
- vkvg_paint(ctx);
- vkvg_set_matrix(ctx,&mat);
+ //vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD);
- vkvg_set_line_width(ctx,10);
- vkvg_set_source_rgba(ctx,0,0,1,1);
+ vkvg_set_source_rgba(ctx,0,0,1,0.5);
vkvg_rectangle(ctx,100,100,200,200);
- /*vkvg_fill(ctx);
+ vkvg_fill(ctx);
+
vkvg_rectangle(ctx,200,200,200,200);
- vkvg_set_source_rgba(ctx,1,0,0,0.5);*/
+ vkvg_set_source_rgba(ctx,1,0,0,0.5);
vkvg_fill(ctx);
vkvg_destroy(ctx);
//vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL);
//vkvg_set_source_rgba(ctx,1.0,0.0,0.0,0.1);
- for (int i=0; i<250; i++) {
+ for (int i=0; i<iterations; i++) {
randomize_color(ctx);
- float x1 = trunc( ((float)w*rand())/RAND_MAX );
- float y1 = trunc( ((float)h*rand())/RAND_MAX );
- float v = trunc( ((float)500*rand())/RAND_MAX ) + 1;
+ float x1 = w*rand()/RAND_MAX;
+ float y1 = h*rand()/RAND_MAX;
+ float v = (500.f*rand()/RAND_MAX) + 1;
vkvg_move_to (ctx, x1, y1);
vkvg_line_to (ctx, x1, y1 + v);