3 #include "radfnptrinit.h"
\r
14 #include <RAD/rad.h>
\r
15 #include <EGL/egl.h>
\r
19 bool useCopyQueue = true;
\r
22 static const char *vsstring =
\r
23 "#version 440 core\n"
\r
24 "#define BINDGROUP(GROUP,INDEX) layout(binding = ((INDEX) | ((GROUP) << 4)))\n"
\r
25 "layout(location = 1) in vec4 tc;\n"
\r
26 "layout(location = 0) in vec4 position;\n"
\r
27 "BINDGROUP(0, 2) uniform Block {\n"
\r
32 " gl_Position = position*scale;\n"
\r
33 // This line exists to trick the compiler into putting a value in the compiler
\r
34 // constant bank, so we can exercise binding that bank
\r
35 " if (scale.z != 1.0 + 1.0/65536.0) {\n"
\r
36 " gl_Position = vec4(0,0,0,0);\n"
\r
41 static const char *fsstring =
\r
42 "#version 440 core\n"
\r
43 "#define BINDGROUP(GROUP,INDEX) layout(binding = ((INDEX) | ((GROUP) << 4)))\n"
\r
44 "BINDGROUP(0, 3) uniform sampler2D tex;\n"
\r
45 "BINDGROUP(0, 2) uniform Block {\n"
\r
48 "layout(location = 0) out vec4 color;\n"
\r
51 " color = texture(tex, ftc.xy);\n"
\r
52 " if (scale.z != 1.0 + 1.0/65536.0) {\n"
\r
53 " color = vec4(0,0,0,0);\n"
\r
58 // Two triangles that intersect
\r
59 static RADfloat vertexData[] = {-0.5f, -0.5f, 0.5f,
\r
67 // Simple 0/1 texcoords in rgba8 format (used to be color data)
\r
68 static RADubyte texcoordData[] = {0, 0, 0xFF, 0xFF,
\r
76 int windowWidth = 500, windowHeight = 500;
\r
77 int offscreenWidth = 100, offscreenHeight = 100;
\r
85 DrawMode drawMode = COMMAND;
\r
86 bool benchmark = false;
\r
90 // obfuscated string for radGetProcAddress
\r
91 PFNRADGETPROCADDRESSPROC getProc = (PFNRADGETPROCADDRESSPROC)eglGetProcAddress("radGetProcAddress");
\r
92 radLoadProcs(getProc);
\r
94 // Create the "global" device and one queue
\r
95 device = radCreateDevice();
\r
96 queue = radCreateQueue(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);
\r
98 copyQueue = radCreateQueue(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);
\r
102 #define USE_MULTISAMPLE 1
\r
104 RADbuffer AllocAndFillBuffer(RADdevice device, void *data, int sizeofdata, RADbitfield access, bool useCopy)
\r
107 RADbuffer tempbo = radCreateBuffer(device);
\r
108 radBufferAccess(tempbo, RAD_COPY_READ_ACCESS_BIT);
\r
109 radBufferMapAccess(tempbo, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);
\r
110 radBufferStorage(tempbo, sizeofdata);
\r
111 void *ptr = radMapBuffer(tempbo);
\r
112 memcpy(ptr, data, sizeofdata);
\r
114 RADbuffer buffer = radCreateBuffer(device);
\r
115 radBufferAccess(buffer, access | RAD_COPY_WRITE_ACCESS_BIT);
\r
116 radBufferMapAccess(buffer, 0);
\r
117 radBufferStorage(buffer, sizeofdata);
\r
119 radQueueCopyBuffer(useCopyQueue ? copyQueue : queue, tempbo, 0, buffer, 0, sizeofdata);
\r
121 radReleaseBuffer(tempbo, RAD_TAG_AUTO);
\r
124 RADbuffer buffer = radCreateBuffer(device);
\r
125 radBufferAccess(buffer, access);
\r
126 radBufferMapAccess(buffer, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);
\r
127 radBufferStorage(buffer, sizeofdata);
\r
128 void *ptr = radMapBuffer(buffer);
\r
129 memcpy(ptr, data, sizeofdata);
\r
136 // Create programs from the device, provide them shader code and compile/link them
\r
137 RADprogram pgm = radCreateProgram(device);
\r
139 // XXX This is a hack because we don't have an IL. I'm just jamming through the strings
\r
140 // as if they were an IL blob
\r
141 const char *source[2] = {vsstring, fsstring};
\r
142 radProgramSource(pgm, RAD_PROGRAM_FORMAT_GLSL, /*size*/2, (void *)source);
\r
144 // Create new state vectors
\r
145 RADcolorState color = radCreateColorState(device);
\r
146 RADdepthStencilState depth = radCreateDepthStencilState(device);
\r
147 RADvertexState vertex = radCreateVertexState(device);
\r
148 RADrasterState raster = radCreateRasterState(device);
\r
149 RADrtFormatState rtFormat = radCreateRtFormatState(device);
\r
152 radRtFormatColorFormat(rtFormat, 0, RAD_RGBA8);
\r
153 radRtFormatDepthFormat(rtFormat, RAD_DEPTH24_STENCIL8);
\r
155 radDepthStencilDepthTestEnable(depth, RAD_TRUE);
\r
156 radDepthStencilDepthWriteEnable(depth, RAD_TRUE);
\r
157 radDepthStencilDepthFunc(depth, RAD_DEPTH_FUNC_LESS);
\r
159 // Commented out experiments to test different state settings.
\r
160 //radRasterDiscardEnable(raster, RAD_TRUE);
\r
161 //radRasterPolygonMode(raster, RAD_POLYGON_MODE_LINE);
\r
162 //radRasterLineWidth(raster, 10.0f);
\r
164 //radColorBlendEnable(color, /*MRT index*/0, RAD_TRUE);
\r
165 //radColorBlendFunc(color, /*MRT index*/0, RAD_BLEND_FUNC_ONE, RAD_BLEND_FUNC_ONE, RAD_BLEND_FUNC_ONE, RAD_BLEND_FUNC_ONE);
\r
166 //radColorMask(color, /*MRT index*/0, RAD_TRUE, RAD_TRUE, RAD_TRUE, RAD_TRUE);
\r
167 //radColorLogicOpEnable(color, RAD_TRUE);
\r
168 //radColorLogicOp(color, RAD_LOGIC_OP_XOR);
\r
170 // Set the state vector to use two vertex attributes.
\r
172 // Interleaved pos+color
\r
173 // position = attrib 0 = 3*float at relativeoffset 0
\r
174 // texcoord = attrib 1 = rgba8 at relativeoffset 0
\r
175 radVertexAttribFormat(vertex, 0, 3, sizeof(RADfloat), RAD_ATTRIB_TYPE_FLOAT, 0);
\r
176 radVertexAttribFormat(vertex, 1, 4, sizeof(RADubyte), RAD_ATTRIB_TYPE_UNORM, 0);
\r
177 radVertexAttribBinding(vertex, 0, 0);
\r
178 radVertexAttribBinding(vertex, 1, 1);
\r
179 radVertexBindingGroup(vertex, 0, /*group*/0, /*index*/0);
\r
180 radVertexBindingGroup(vertex, 1, /*group*/0, /*index*/1);
\r
181 radVertexAttribEnable(vertex, 0, RAD_TRUE);
\r
182 radVertexAttribEnable(vertex, 1, RAD_TRUE);
\r
183 radVertexBindingStride(vertex, 0, 12);
\r
184 radVertexBindingStride(vertex, 1, 4);
\r
186 // Create a pipeline.
\r
187 RADpipeline pipeline = radCreatePipeline(device, RAD_PIPELINE_TYPE_GRAPHICS);
\r
189 // Attach program and state objects to the pipeline.
\r
190 radPipelineProgramStages(pipeline, RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT, pgm);
\r
191 radPipelineColorState(pipeline, color);
\r
192 radPipelineDepthStencilState(pipeline, depth);
\r
193 radPipelineVertexState(pipeline, vertex);
\r
194 radPipelineRasterState(pipeline, raster);
\r
195 radPipelineRtFormatState(pipeline, rtFormat);
\r
196 radPipelinePrimitiveType(pipeline, RAD_TRIANGLES);
\r
198 // Create a vertex buffer and fill it with data
\r
199 RADbuffer vbo = radCreateBuffer(device);
\r
200 radBufferAccess(vbo, RAD_VERTEX_ACCESS_BIT);
\r
201 radBufferMapAccess(vbo, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);
\r
202 radBufferStorage(vbo, sizeof(vertexData)+sizeof(texcoordData));
\r
203 // create persistent mapping
\r
204 void *ptr = radMapBuffer(vbo);
\r
205 // fill ptr with vertex data followed by color data
\r
206 memcpy(ptr, vertexData, sizeof(vertexData));
\r
207 memcpy((char *)ptr + sizeof(vertexData), texcoordData, sizeof(texcoordData));
\r
209 // Get a handle to be used for setting the buffer as a vertex buffer
\r
210 RADvertexHandle vboHandle = radGetVertexHandle(vbo);
\r
212 // Create an index buffer and fill it with data
\r
213 unsigned short indexData[6] = {0, 1, 2, 3, 4, 5};
\r
214 RADbuffer ibo = AllocAndFillBuffer(device, indexData, sizeof(indexData), RAD_INDEX_ACCESS_BIT, true);
\r
216 // Get a handle to be used for setting the buffer as an index buffer
\r
217 RADvertexHandle iboHandle = radGetVertexHandle(ibo);
\r
219 float scale = 1.5f;
\r
223 float uboData[4] = {scale, scale, 1.0f + 1.0f/65536.0, 1.0f};
\r
224 RADbuffer ubo = AllocAndFillBuffer(device, uboData, sizeof(uboData), RAD_UNIFORM_ACCESS_BIT, false);
\r
226 // Get a handle to be used for setting the buffer as a uniform buffer
\r
227 RADuniformHandle uboHandle = radGetUniformHandle(ubo);
\r
229 #if USE_MULTISAMPLE
\r
230 RADtexture rtTex = radCreateTexture(device);
\r
231 radTextureAccess(rtTex, RAD_RENDER_TARGET_ACCESS_BIT);
\r
232 radTextureStorage(rtTex, RAD_TEXTURE_2D_MULTISAMPLE, 1, RAD_RGBA8, offscreenWidth, offscreenHeight, 1, 4);
\r
234 RADtexture depthTex = radCreateTexture(device);
\r
235 radTextureAccess(depthTex, RAD_RENDER_TARGET_ACCESS_BIT);
\r
236 radTextureStorage(depthTex, RAD_TEXTURE_2D_MULTISAMPLE, 1, RAD_DEPTH24_STENCIL8, offscreenWidth, offscreenHeight, 1, 4);
\r
238 RADtexture tex1x = radCreateTexture(device);
\r
239 radTextureAccess(tex1x, RAD_RENDER_TARGET_ACCESS_BIT);
\r
240 radTextureStorage(tex1x, RAD_TEXTURE_2D, 1, RAD_RGBA8, offscreenWidth, offscreenHeight, 1, 0);
\r
242 // Create and bind a rendertarget handle
\r
243 RADrenderTargetHandle rtHandle = radGetTextureRenderTargetHandle(rtTex, RAD_TEXTURE_2D, RAD_RGBA8, 0, 0, 1);
\r
244 RADrenderTargetHandle depthHandle = radGetTextureRenderTargetHandle(depthTex, RAD_TEXTURE_2D, RAD_DEPTH24_STENCIL8, 0, 0, 1);
\r
246 radRasterSamples(raster, 4);
\r
247 radRtFormatColorSamples(rtFormat, 4);
\r
248 radRtFormatDepthStencilSamples(rtFormat, 4);
\r
250 RADpass pass = radCreatePass(device);
\r
251 radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);
\r
252 radPassResolve(pass, RAD_RT_ATTACHMENT_COLOR0, tex1x);
\r
254 RADtexture rtTex = radCreateTexture(device);
\r
255 radTextureAccess(rtTex, RAD_RENDER_TARGET_ACCESS_BIT);
\r
256 radTextureStorage(rtTex, RAD_TEXTURE_2D, 1, RAD_RGBA8, offscreenWidth, offscreenHeight, 1, 0);
\r
258 RADtexture depthTex = radCreateTexture(device);
\r
259 radTextureAccess(depthTex, RAD_RENDER_TARGET_ACCESS_BIT);
\r
260 radTextureStorage(depthTex, RAD_TEXTURE_2D, 1, RAD_DEPTH24_STENCIL8, offscreenWidth, offscreenHeight, 1, 0);
\r
262 // Create and bind a rendertarget handle
\r
263 RADrenderTargetHandle rtHandle = radGetTextureRenderTargetHandle(rtTex, RAD_TEXTURE_2D, RAD_RGBA8, 0, 0, 1);
\r
264 RADrenderTargetHandle depthHandle = radGetTextureRenderTargetHandle(depthTex, RAD_TEXTURE_2D, RAD_DEPTH24_STENCIL8, 0, 0, 1);
\r
266 RADpass pass = radCreatePass(device);
\r
267 radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);
\r
270 radCompilePass(pass);
\r
272 radCompilePipeline(pipeline);
\r
273 RADpipelineHandle pipelineHandle = radGetPipelineHandle(pipeline);
\r
275 RADsampler sampler = radCreateSampler(device);
\r
276 // Commented out experiments to test different state settings.
\r
277 //radSamplerMinMagFilter(sampler, RAD_MIN_FILTER_NEAREST, RAD_MAG_FILTER_NEAREST);
\r
279 const int texWidth = 4, texHeight = 4;
\r
280 RADtexture texture = radCreateTexture(device);
\r
281 radTextureAccess(texture, RAD_TEXTURE_ACCESS_BIT);
\r
282 radTextureStorage(texture, RAD_TEXTURE_2D, 1, RAD_RGBA8, texWidth, texHeight, 1, 0);
\r
283 RADtextureHandle texHandle = radGetTextureSamplerHandle(texture, sampler, RAD_TEXTURE_2D, RAD_RGBA8,
\r
284 /*minLevel*/0, /*numLevels*/1, /*minLayer*/0, /*numLayers*/1);
\r
286 RADbuffer pbo = radCreateBuffer(device);
\r
287 radBufferAccess(pbo, RAD_COPY_READ_ACCESS_BIT);
\r
288 radBufferMapAccess(pbo, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);
\r
289 radBufferStorage(pbo, texWidth*texHeight*4);
\r
291 unsigned char *texdata = (unsigned char *)radMapBuffer(pbo);
\r
292 // fill with texture data
\r
293 for (int j = 0; j < texWidth; ++j) {
\r
294 for (int i = 0; i < texHeight; ++i) {
\r
295 texdata[4*(j*texWidth+i)+0] = 0xFF*((i+j)&1);
\r
296 texdata[4*(j*texWidth+i)+1] = 0x00*((i+j)&1);
\r
297 texdata[4*(j*texWidth+i)+2] = ~(0xFF*((i+j)&1));
\r
298 texdata[4*(j*texWidth+i)+3] = 0xFF;
\r
302 // XXX missing pixelpack object
\r
303 // Download the texture data
\r
304 radQueueCopyBufferToImage(queue, pbo, 0, texture, 0, 0, 0, 0, texWidth, texHeight, 1);
\r
306 radQueueBeginPass(queue, pass);
\r
308 // Some scissored clears
\r
310 radQueueScissor(queue, 0, 0, offscreenWidth, offscreenHeight);
\r
311 float clearColor[4] = {0, 0, 0, 1};
\r
312 radQueueClearColor(queue, 0, clearColor);
\r
313 radQueueClearDepth(queue, 1.0f);
\r
316 radQueueScissor(queue, 0, 0, offscreenWidth/2, offscreenHeight/2);
\r
317 float clearColor[4] = {0, 1, 0, 1};
\r
318 radQueueClearColor(queue, 0, clearColor);
\r
321 radQueueScissor(queue, offscreenWidth/2, offscreenHeight/2, offscreenWidth/2, offscreenHeight/2);
\r
322 float clearColor[4] = {0, 0, 1, 1};
\r
323 radQueueClearColor(queue, 0, clearColor);
\r
325 radQueueScissor(queue, 0, 0, offscreenWidth, offscreenHeight);
\r
326 radQueueViewport(queue, 0, 0, offscreenWidth, offscreenHeight);
\r
328 RADbindGroupElement b[4] = {{vboHandle, 0, ~0}, {vboHandle, sizeof(vertexData), ~0}, {uboHandle, 0, 4*sizeof(float)}, {texHandle, 0, ~0}};
\r
329 RADbuffer bindGroup = AllocAndFillBuffer(device, b, sizeof(b), RAD_BINDGROUP_ACCESS_BIT, false);
\r
331 RADbindGroupHandle bindGroupHandle = radGetBindGroupHandle(bindGroup);
\r
333 if (useCopyQueue) {
\r
334 // Sync from copy queue to graphics queue. Note that we currently don't sync in the
\r
335 // opposite direction at the end of the frame, because radQueuePresent effectively
\r
336 // does a Finish so it isn't needed.
\r
337 RADsync sync = radCreateSync(device);
\r
338 radQueueFenceSync(copyQueue, sync, RAD_SYNC_ALL_GPU_COMMANDS_COMPLETE, 0);
\r
339 radQueueWaitSync(queue, sync);
\r
340 radReleaseSync(sync);
\r
343 clock_t startTime = clock();
\r
344 unsigned int numIterations = benchmark ? 1000000 : 1;
\r
346 switch (drawMode) {
\r
348 for (unsigned int i = 0; i < numIterations; ++i) {
\r
349 // Bind the pipeline, bind vertex arrays and textures, and draw
\r
350 radQueueBindPipeline(queue, RAD_PIPELINE_TYPE_GRAPHICS, pipelineHandle);
\r
351 radQueueBindGroup(queue, RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT, 0, 4, bindGroupHandle, 0);
\r
352 //radQueueDrawArrays(queue, RAD_TRIANGLES, 0, 6);
\r
353 radQueueDrawElements(queue, RAD_TRIANGLES, RAD_INDEX_UNSIGNED_SHORT, 6, iboHandle, 0);
\r
358 typedef struct Draw {
\r
359 RADuint pipelineHeader;
\r
360 RADtokenBindGraphicsPipeline pipeline;
\r
361 RADuint bindGroupHeader;
\r
362 RADtokenBindGroup bindGroup;
\r
363 RADuint drawElementsHeader;
\r
364 RADtokenDrawElements drawElements;
\r
367 memset(&d, 0, sizeof(d));
\r
368 d.pipelineHeader = radGetTokenHeader(device, RAD_TOKEN_BIND_GRAPHICS_PIPELINE);
\r
369 d.pipeline.pipelineHandle = pipelineHandle;
\r
370 d.bindGroupHeader = radGetTokenHeader(device, RAD_TOKEN_BIND_GROUP);
\r
371 d.bindGroup.stages = RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT;
\r
372 d.bindGroup.group = 0;
\r
373 d.bindGroup.groupHandle = bindGroupHandle;
\r
374 d.bindGroup.offset = 0;
\r
375 d.bindGroup.count = 4;
\r
376 d.drawElementsHeader = radGetTokenHeader(device, RAD_TOKEN_DRAW_ELEMENTS);
\r
377 d.drawElements.indexHandle = iboHandle;
\r
378 d.drawElements.mode = RAD_TRIANGLES;
\r
379 d.drawElements.type = RAD_INDEX_UNSIGNED_SHORT;
\r
380 d.drawElements.count = 6;
\r
381 for (unsigned int i = 0; i < numIterations; ++i) {
\r
382 radQueueSubmitDynamic(queue, &d, sizeof(d));
\r
388 RADcommandBuffer cmd = radCreateCommandBuffer(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);
\r
389 radCmdBindPipeline(cmd, RAD_PIPELINE_TYPE_GRAPHICS, pipelineHandle);
\r
390 radCmdBindGroup(cmd, RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT, 0, 4, bindGroupHandle, 0);
\r
391 radCmdDrawElements(cmd, RAD_TRIANGLES, RAD_INDEX_UNSIGNED_SHORT, 6, iboHandle, 0);
\r
392 radCompileCommandBuffer(cmd);
\r
393 RADcommandHandle cmdHandle = radGetCommandHandle(cmd);
\r
394 for (unsigned int i = 0; i < numIterations; ++i) {
\r
395 radQueueSubmitCommands(queue, 1, &cmdHandle);
\r
397 radReleaseCommandBuffer(cmd);
\r
403 clock_t currentTime = clock();
\r
404 printf("%f\n", 1.0f*numIterations*CLOCKS_PER_SEC/(currentTime - startTime));
\r
407 radQueueEndPass(queue, pass);
\r
409 // Kickoff submitted command buffers for the queue
\r
410 //radFlushQueue(queue);
\r
412 #if USE_MULTISAMPLE
\r
413 radQueuePresent(queue, tex1x);
\r
415 radQueuePresent(queue, rtTex);
\r
418 radReleaseProgram(pgm);
\r
419 radReleaseColorState(color);
\r
420 radReleaseDepthStencilState(depth);
\r
421 radReleaseVertexState(vertex);
\r
422 radReleaseRasterState(raster);
\r
423 radReleaseRtFormatState(rtFormat);
\r
424 radReleaseBuffer(vbo, RAD_TAG_AUTO);
\r
425 radReleaseBuffer(ibo, RAD_TAG_AUTO);
\r
426 radReleaseBuffer(pbo, RAD_TAG_AUTO);
\r
427 radReleaseBuffer(ubo, RAD_TAG_AUTO);
\r
428 radReleaseBuffer(bindGroup, RAD_TAG_AUTO);
\r
429 radReleaseTexture(texture, RAD_TAG_AUTO);
\r
430 radReleaseTexture(rtTex, RAD_TAG_AUTO);
\r
431 radReleaseTexture(depthTex, RAD_TAG_AUTO);
\r
432 radReleaseSampler(sampler);
\r
433 radReleasePipeline(pipeline);
\r
434 radReleasePass(pass);
\r
435 #if USE_MULTISAMPLE
\r
436 radReleaseTexture(tex1x, RAD_TAG_AUTO);
\r