summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/zink/zink_query.c
blob: 65babe5d763638a3e2c4676fc93199297e7e77e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

#include "zink_context.h"
#include "zink_screen.h"

#include "util/u_memory.h"
struct zink_query {
   VkQueryPool queryPool;
   VkQueryType vkqtype;
   bool use_64bit;
   bool precise;
};

static VkQueryType
convert_query_type(unsigned query_type, bool *use_64bit, bool *precise)
{
   *use_64bit = false;
   *precise = false;
   switch (query_type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      *precise = true;
      *use_64bit = true;
   case PIPE_QUERY_OCCLUSION_PREDICATE:
   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
      return VK_QUERY_TYPE_OCCLUSION;
   case PIPE_QUERY_TIMESTAMP:
      *use_64bit = true;
      return VK_QUERY_TYPE_TIMESTAMP;
   case PIPE_QUERY_PIPELINE_STATISTICS:
      return VK_QUERY_TYPE_PIPELINE_STATISTICS;
   default:
      fprintf(stderr, "zink: unknown query type\n");
      return -1;
   }
}

static struct pipe_query *
zink_create_query(struct pipe_context *pctx,
                  unsigned query_type, unsigned index)
{
   struct zink_screen *screen = zink_screen(pctx->screen);
   struct zink_query *query = CALLOC_STRUCT(zink_query);
   VkQueryPoolCreateInfo pool_create = {};

   if (!query)
      return NULL;

   query->vkqtype = convert_query_type(query_type, &query->use_64bit, &query->precise);
   if (query->vkqtype == -1)
      return NULL;

   pool_create.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
   pool_create.queryType = query->vkqtype;
   pool_create.queryCount = 1;

   VkResult status = vkCreateQueryPool(screen->dev, &pool_create, NULL, &query->queryPool);
   if (status != VK_SUCCESS) {
      FREE(query);
      return NULL;
   }
   return (struct pipe_query *)query;
}

static void
zink_destroy_query(struct pipe_context *pctx,
                   struct pipe_query *q)
{
   struct zink_screen *screen = zink_screen(pctx->screen);
   struct zink_query *query = CALLOC_STRUCT(zink_query);

   vkDestroyQueryPool(screen->dev, query->queryPool, NULL);
}

static bool
zink_begin_query(struct pipe_context *pctx,
                 struct pipe_query *q)
{
   struct zink_context *ctx = zink_context(pctx);
   struct zink_query *query = (struct zink_query *)q;

   struct zink_cmdbuf *cmdbuf = zink_start_cmdbuf(ctx);
   if (!cmdbuf)
      return false;

   if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP)
      return true;

   VkQueryControlFlags flags = 0;
   if (query->precise)
      flags |= VK_QUERY_CONTROL_PRECISE_BIT;

   vkCmdBeginQuery(cmdbuf->cmdbuf, query->queryPool, 0, flags);

   return true;
}

static bool
zink_end_query(struct pipe_context *pctx,
               struct pipe_query *q)
{
   struct zink_context *ctx = zink_context(pctx);
   struct zink_query *query = (struct zink_query *)q;

   struct zink_cmdbuf *cmdbuf = zink_start_cmdbuf(ctx);
   if (!cmdbuf)
      return false;

   if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP)
      vkCmdWriteTimestamp(cmdbuf->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
                          query->queryPool, 0);
   else
      vkCmdEndQuery(cmdbuf->cmdbuf, query->queryPool, 0);
   return true;
}

static bool
zink_get_query_result(struct pipe_context *pctx,
                      struct pipe_query *q,
                      bool wait,
                      union pipe_query_result *result)
{
   struct zink_screen *screen = zink_screen(pctx->screen);
   struct zink_query *query = (struct zink_query *)q;
   VkQueryResultFlagBits flags = 0;

   pctx->flush(pctx, NULL, 0);

   if (wait)
      flags |= VK_QUERY_RESULT_WAIT_BIT;

   if (query->use_64bit)
      flags |= VK_QUERY_RESULT_64_BIT;

   VkResult status = vkGetQueryPoolResults(screen->dev, query->queryPool,
                                           0, 1, sizeof(*result), result,
                                           0, flags);
   return status == VK_SUCCESS;
}

void
zink_context_query_init(struct pipe_context *pctx)
{
   pctx->create_query = zink_create_query;
   pctx->destroy_query = zink_destroy_query;
   pctx->begin_query = zink_begin_query;
   pctx->end_query = zink_end_query;
   pctx->get_query_result = zink_get_query_result;
}