OSDN Git Service

Implement a Radiance prototype.
[android-x86/external-swiftshader.git] / tests / HelloRAD / src / app / radexample.cpp
1 \r
2 #include "stdlib.h"\r
3 #include "radfnptrinit.h"\r
4 #include "string.h"\r
5 #ifdef _WIN32\r
6 #include <windows.h>\r
7 #endif\r
8 #ifdef __linux__\r
9 #include <GL/glx.h>\r
10 #endif\r
11 #include <stdio.h>\r
12 #include <time.h>\r
13 \r
14 #include <RAD/rad.h>\r
15 #include <EGL/egl.h>\r
16 \r
17 RADdevice device;\r
18 RADqueue queue;\r
19 bool useCopyQueue = false /*true*/;\r
20 RADqueue copyQueue;\r
21  \r
22 #define SHADER_SOURCE(source) #source\r
23 \r
24 static const char *vsstring = \r
25     //"#version 440 core\n"\r
26     //"#define BINDGROUP(GROUP,INDEX) layout(binding = ((INDEX) | ((GROUP) << 4)))\n"\r
27     //"layout(location = 1) in vec4 tc;\n"\r
28     //"layout(location = 0) in vec4 position;\n"\r
29     //"BINDGROUP(0, 2) uniform Block {\n"\r
30     //"    vec4 scale;\n"\r
31     //"};\n"\r
32     //"out vec4 ftc;\n"\r
33     //"void main() {\n"\r
34     //"  gl_Position = position*scale;\n"\r
35     //// This line exists to trick the compiler into putting a value in the compiler\r
36     //// constant bank, so we can exercise binding that bank\r
37     //"  if (scale.z != 1.0 + 1.0/65536.0) {\n"\r
38     //"      gl_Position = vec4(0,0,0,0);\n"\r
39     //"  }\n"\r
40     //"  ftc = tc;\n"\r
41     //"}\n";\r
42 SHADER_SOURCE(attribute highp vec4      position;\r
43               attribute highp vec4      tc;\r
44               varying highp vec4 ftc;\r
45               uniform highp vec4 scale;\r
46               void main(void)\r
47               {\r
48                                 gl_Position = position * scale;\r
49                                 ftc = tc;\r
50               });\r
51 \r
52 static const char *fsstring = \r
53    /* "#version 440 core\n"\r
54     "#define BINDGROUP(GROUP,INDEX) layout(binding = ((INDEX) | ((GROUP) << 4)))\n"\r
55     "BINDGROUP(0, 3) uniform sampler2D tex;\n"\r
56     "BINDGROUP(0, 2) uniform Block {\n"\r
57     "    vec4 scale;\n"\r
58     "};\n"\r
59     "layout(location = 0) out vec4 color;\n"\r
60     "in vec4 ftc;\n"\r
61     "void main() {\n"\r
62     "  color = texture(tex, ftc.xy);\n"\r
63     "  if (scale.z != 1.0 + 1.0/65536.0) {\n"\r
64     "      color = vec4(0,0,0,0);\n"\r
65     "  }\n"\r
66     "}\n";*/\r
67                 SHADER_SOURCE(\r
68                         varying highp vec4 ftc;\r
69                         uniform sampler2D tex;\r
70                         void main (void)\r
71                         {\r
72                                 gl_FragColor = texture2D(tex, ftc.xy);\n\r
73                         });\r
74 \r
75 \r
76 // Two triangles that intersect\r
77 static RADfloat vertexData[] = {-0.5f, -0.5f, 0.5f, \r
78                                 0.5f, -0.5f,  0.5f,\r
79                                 -0.5f, 0.5f,  0.5f,\r
80 \r
81                                 0.5f, -0.5f, 0.5f,\r
82                                 -0.5f, -0.5f, 0.3f,\r
83                                 0.5f, 0.5f, 0.9f};\r
84 \r
85 // Simple 0/1 texcoords in rgba8 format (used to be color data)\r
86 static RADubyte texcoordData[] = {0, 0, 0xFF, 0xFF,\r
87                                   0xFF, 0, 0, 0xFF,\r
88                                   0, 0xFF, 0, 0xFF,\r
89 \r
90                                   0, 0, 0xFF, 0xFF,\r
91                                   0xFF, 0, 0, 0xFF,\r
92                                   0, 0xFF, 0, 0xFF};\r
93 \r
94 int windowWidth = 500, windowHeight = 500;\r
95 int offscreenWidth = 500, offscreenHeight = 500;\r
96 \r
97 typedef enum {\r
98     QUEUE,\r
99     TOKEN,\r
100     COMMAND,\r
101 } DrawMode;\r
102 \r
103 DrawMode drawMode = QUEUE /* COMMAND */;\r
104 bool benchmark = false;\r
105 \r
106 void InitRAD()\r
107 {\r
108     // obfuscated string for radGetProcAddress\r
109         PFNRADGETPROCADDRESSPROC getProc = (PFNRADGETPROCADDRESSPROC)eglGetProcAddress("radGetProcAddress");\r
110     radLoadProcs(getProc);\r
111 \r
112     // Create the "global" device and one queue\r
113     device = radCreateDevice();\r
114     queue = radCreateQueue(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);\r
115     if (useCopyQueue) {\r
116         copyQueue = radCreateQueue(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);\r
117     }\r
118 }\r
119 \r
120 void CleanRAD()\r
121 {\r
122     if (useCopyQueue) {\r
123                 radReleaseQueue(copyQueue);\r
124     }\r
125         radReleaseQueue(queue);\r
126         radReleaseDevice(device);\r
127 }\r
128 \r
129 #define USE_MULTISAMPLE 0\r
130 \r
131 RADbuffer AllocAndFillBuffer(RADdevice device, void *data, int sizeofdata, RADbitfield access, bool useCopy)\r
132 {\r
133     if (useCopy) {\r
134         RADbuffer tempbo = radCreateBuffer(device);\r
135         radBufferAccess(tempbo, RAD_COPY_READ_ACCESS_BIT);\r
136         radBufferMapAccess(tempbo, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);\r
137         radBufferStorage(tempbo, sizeofdata);\r
138         void *ptr = radMapBuffer(tempbo);\r
139         memcpy(ptr, data, sizeofdata);\r
140 \r
141         RADbuffer buffer = radCreateBuffer(device);\r
142         radBufferAccess(buffer, access | RAD_COPY_WRITE_ACCESS_BIT);\r
143         radBufferMapAccess(buffer, 0);\r
144         radBufferStorage(buffer, sizeofdata);\r
145 \r
146         radQueueCopyBuffer(useCopyQueue ? copyQueue : queue, tempbo, 0, buffer, 0, sizeofdata);\r
147 \r
148         radReleaseBuffer(tempbo, RAD_TAG_AUTO);\r
149         return buffer;\r
150     } else {\r
151         RADbuffer buffer = radCreateBuffer(device);\r
152         radBufferAccess(buffer, access);\r
153         radBufferMapAccess(buffer, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);\r
154         radBufferStorage(buffer, sizeofdata);\r
155         void *ptr = radMapBuffer(buffer);\r
156         memcpy(ptr, data, sizeofdata);\r
157         return buffer;\r
158     }\r
159 }\r
160 \r
161 void TestRAD()\r
162 {\r
163     // Create programs from the device, provide them shader code and compile/link them\r
164     RADprogram pgm = radCreateProgram(device);\r
165 \r
166     // XXX This is a hack because we don't have an IL. I'm just jamming through the strings \r
167     // as if they were an IL blob\r
168     const char *source[2] = {vsstring, fsstring};\r
169     radProgramSource(pgm, RAD_PROGRAM_FORMAT_GLSL, /*size*/2, (void *)source);\r
170 \r
171     // Create new state vectors\r
172     RADcolorState color = radCreateColorState(device);\r
173     RADdepthStencilState depth = radCreateDepthStencilState(device);\r
174     RADvertexState vertex = radCreateVertexState(device);\r
175     RADrasterState raster = radCreateRasterState(device);\r
176     RADrtFormatState rtFormat = radCreateRtFormatState(device);\r
177 \r
178 \r
179     radRtFormatColorFormat(rtFormat, 0, RAD_RGBA8);\r
180     radRtFormatDepthFormat(rtFormat, RAD_DEPTH24_STENCIL8);\r
181 \r
182     radDepthStencilDepthTestEnable(depth, RAD_TRUE);\r
183     radDepthStencilDepthWriteEnable(depth, RAD_TRUE);\r
184     radDepthStencilDepthFunc(depth, RAD_DEPTH_FUNC_LESS);\r
185 \r
186     // Commented out experiments to test different state settings.    \r
187     //radRasterDiscardEnable(raster, RAD_TRUE);\r
188     //radRasterPolygonMode(raster, RAD_POLYGON_MODE_LINE);\r
189     //radRasterLineWidth(raster, 10.0f);\r
190 \r
191     //radColorBlendEnable(color, /*MRT index*/0, RAD_TRUE);\r
192     //radColorBlendFunc(color, /*MRT index*/0, RAD_BLEND_FUNC_ONE, RAD_BLEND_FUNC_ONE, RAD_BLEND_FUNC_ONE, RAD_BLEND_FUNC_ONE);\r
193     //radColorMask(color, /*MRT index*/0, RAD_TRUE, RAD_TRUE, RAD_TRUE, RAD_TRUE);\r
194     //radColorLogicOpEnable(color, RAD_TRUE);\r
195     //radColorLogicOp(color, RAD_LOGIC_OP_XOR);\r
196 \r
197     // Set the state vector to use two vertex attributes.\r
198     //\r
199     // Interleaved pos+color\r
200     // position = attrib 0 = 3*float at relativeoffset 0\r
201     // texcoord = attrib 1 = rgba8 at relativeoffset 0\r
202     radVertexAttribFormat(vertex, 0, 3, sizeof(RADfloat), RAD_ATTRIB_TYPE_FLOAT, 0);\r
203     radVertexAttribFormat(vertex, 1, 4, sizeof(RADubyte), RAD_ATTRIB_TYPE_UNORM, 0);\r
204     radVertexAttribBinding(vertex, 0, 0);\r
205     radVertexAttribBinding(vertex, 1, 1);\r
206     radVertexBindingGroup(vertex, 0, /*group*/0, /*index*/0);\r
207     radVertexBindingGroup(vertex, 1, /*group*/0, /*index*/1);\r
208     radVertexAttribEnable(vertex, 0, RAD_TRUE);\r
209     radVertexAttribEnable(vertex, 1, RAD_TRUE);\r
210     radVertexBindingStride(vertex, 0, 12);\r
211     radVertexBindingStride(vertex, 1, 4);\r
212 \r
213     // Create a pipeline.\r
214     RADpipeline pipeline = radCreatePipeline(device, RAD_PIPELINE_TYPE_GRAPHICS);\r
215 \r
216     // Attach program and state objects to the pipeline.\r
217     radPipelineProgramStages(pipeline, RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT, pgm);\r
218     radPipelineColorState(pipeline, color);\r
219     radPipelineDepthStencilState(pipeline, depth);\r
220     radPipelineVertexState(pipeline, vertex);\r
221     radPipelineRasterState(pipeline, raster);\r
222     radPipelineRtFormatState(pipeline, rtFormat);\r
223     radPipelinePrimitiveType(pipeline, RAD_TRIANGLES);\r
224 \r
225     // Create a vertex buffer and fill it with data\r
226     RADbuffer vbo = radCreateBuffer(device);\r
227     radBufferAccess(vbo, RAD_VERTEX_ACCESS_BIT);\r
228     radBufferMapAccess(vbo, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);\r
229     radBufferStorage(vbo, sizeof(vertexData)+sizeof(texcoordData));\r
230     // create persistent mapping\r
231     void *ptr = radMapBuffer(vbo);\r
232     // fill ptr with vertex data followed by color data\r
233     memcpy(ptr, vertexData, sizeof(vertexData));\r
234     memcpy((char *)ptr + sizeof(vertexData), texcoordData, sizeof(texcoordData));\r
235 \r
236     // Get a handle to be used for setting the buffer as a vertex buffer\r
237     RADvertexHandle vboHandle = radGetVertexHandle(vbo);\r
238 \r
239     // Create an index buffer and fill it with data\r
240     unsigned short indexData[6] = {0, 1, 2, 3, 4, 5};\r
241     RADbuffer ibo = AllocAndFillBuffer(device, indexData, sizeof(indexData), RAD_INDEX_ACCESS_BIT, false /*true*/);\r
242 \r
243     // Get a handle to be used for setting the buffer as an index buffer\r
244     RADvertexHandle iboHandle = radGetVertexHandle(ibo);\r
245 \r
246     float scale = 1.5f;\r
247     if (benchmark) {\r
248         scale = 0.2f;\r
249     }\r
250     float uboData[4] = {scale, scale, 1.0f + 1.0f/65536.0, 1.0f};\r
251     RADbuffer ubo = AllocAndFillBuffer(device, uboData, sizeof(uboData), RAD_UNIFORM_ACCESS_BIT, false);\r
252 \r
253     // Get a handle to be used for setting the buffer as a uniform buffer\r
254     RADuniformHandle uboHandle = radGetUniformHandle(ubo);\r
255 \r
256 #if USE_MULTISAMPLE\r
257     RADtexture rtTex = radCreateTexture(device);\r
258     radTextureAccess(rtTex, RAD_RENDER_TARGET_ACCESS_BIT);\r
259     radTextureStorage(rtTex, RAD_TEXTURE_2D_MULTISAMPLE, 1, RAD_RGBA8, offscreenWidth, offscreenHeight, 1, 4);\r
260 \r
261     RADtexture depthTex = radCreateTexture(device);\r
262     radTextureAccess(depthTex, RAD_RENDER_TARGET_ACCESS_BIT);\r
263     radTextureStorage(depthTex, RAD_TEXTURE_2D_MULTISAMPLE, 1, RAD_DEPTH24_STENCIL8, offscreenWidth, offscreenHeight, 1, 4);\r
264 \r
265     RADtexture tex1x = radCreateTexture(device);\r
266     radTextureAccess(tex1x, RAD_RENDER_TARGET_ACCESS_BIT);\r
267     radTextureStorage(tex1x, RAD_TEXTURE_2D, 1, RAD_RGBA8, offscreenWidth, offscreenHeight, 1, 0);\r
268 \r
269     // Create and bind a rendertarget handle\r
270     RADrenderTargetHandle rtHandle = radGetTextureRenderTargetHandle(rtTex, RAD_TEXTURE_2D, RAD_RGBA8, 0, 0, 1);\r
271     RADrenderTargetHandle depthHandle = radGetTextureRenderTargetHandle(depthTex, RAD_TEXTURE_2D, RAD_DEPTH24_STENCIL8, 0, 0, 1);\r
272 \r
273     radRasterSamples(raster, 4);\r
274     radRtFormatColorSamples(rtFormat, 4);\r
275     radRtFormatDepthStencilSamples(rtFormat, 4);\r
276 \r
277     RADpass pass = radCreatePass(device);\r
278     radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);\r
279     radPassResolve(pass, RAD_RT_ATTACHMENT_COLOR0, tex1x);\r
280 #else\r
281     RADtexture rtTex = radCreateTexture(device);\r
282     radTextureAccess(rtTex, RAD_RENDER_TARGET_ACCESS_BIT);\r
283     radTextureStorage(rtTex, RAD_TEXTURE_2D, 1, RAD_RGBA8, offscreenWidth, offscreenHeight, 1, 0);\r
284 \r
285     RADtexture depthTex = radCreateTexture(device);\r
286     radTextureAccess(depthTex, RAD_RENDER_TARGET_ACCESS_BIT);\r
287     radTextureStorage(depthTex, RAD_TEXTURE_2D, 1, RAD_DEPTH24_STENCIL8, offscreenWidth, offscreenHeight, 1, 0);\r
288 \r
289     // Create and bind a rendertarget handle\r
290     RADrenderTargetHandle rtHandle = radGetTextureRenderTargetHandle(rtTex, RAD_TEXTURE_2D, RAD_RGBA8, 0, 0, 1);\r
291     RADrenderTargetHandle depthHandle = radGetTextureRenderTargetHandle(depthTex, RAD_TEXTURE_2D, RAD_DEPTH24_STENCIL8, 0, 0, 1);\r
292 \r
293     RADpass pass = radCreatePass(device);\r
294     radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);\r
295 #endif\r
296 \r
297     radCompilePass(pass);\r
298 \r
299     radCompilePipeline(pipeline);\r
300     RADpipelineHandle pipelineHandle = radGetPipelineHandle(pipeline);\r
301 \r
302     RADsampler sampler = radCreateSampler(device);\r
303     // Commented out experiments to test different state settings.    \r
304     //radSamplerMinMagFilter(sampler, RAD_MIN_FILTER_NEAREST, RAD_MAG_FILTER_NEAREST);\r
305 \r
306     const int texWidth = 4, texHeight = 4;\r
307     RADtexture texture = radCreateTexture(device);\r
308     radTextureAccess(texture, RAD_TEXTURE_ACCESS_BIT);\r
309     radTextureStorage(texture, RAD_TEXTURE_2D, 1, RAD_RGBA8, texWidth, texHeight, 1, 0);\r
310     RADtextureHandle texHandle = radGetTextureSamplerHandle(texture, sampler, RAD_TEXTURE_2D, RAD_RGBA8, \r
311                                                             /*minLevel*/0, /*numLevels*/1, /*minLayer*/0, /*numLayers*/1);\r
312 \r
313     RADbuffer pbo = radCreateBuffer(device);\r
314     radBufferAccess(pbo, RAD_COPY_READ_ACCESS_BIT);\r
315     radBufferMapAccess(pbo, RAD_MAP_WRITE_BIT | RAD_MAP_PERSISTENT_BIT);\r
316     radBufferStorage(pbo, texWidth*texHeight*4);\r
317 \r
318     unsigned char *texdata = (unsigned char *)radMapBuffer(pbo);\r
319     // fill with texture data\r
320     for (int j = 0; j < texWidth; ++j) {\r
321         for (int i = 0; i < texHeight; ++i) {\r
322             texdata[4*(j*texWidth+i)+0] = 0xFF*((i+j)&1);\r
323             texdata[4*(j*texWidth+i)+1] = 0x00*((i+j)&1);\r
324             texdata[4*(j*texWidth+i)+2] = ~(0xFF*((i+j)&1));\r
325             texdata[4*(j*texWidth+i)+3] = 0xFF;\r
326         }\r
327     }\r
328 \r
329     // XXX missing pixelpack object\r
330     // Download the texture data\r
331     radQueueCopyBufferToImage(queue, pbo, 0, texture, 0, 0, 0, 0, texWidth, texHeight, 1);\r
332 \r
333     radQueueBeginPass(queue, pass);\r
334 \r
335     // Some scissored clears\r
336     {\r
337         radQueueScissor(queue, 0, 0, offscreenWidth, offscreenHeight);\r
338         float clearColor[4] = {0, 0, 0, 1};\r
339         radQueueClearColor(queue, 0, clearColor);\r
340         radQueueClearDepth(queue, 1.0f);\r
341     }\r
342     {\r
343         radQueueScissor(queue, 0, 0, offscreenWidth/2, offscreenHeight/2);\r
344         float clearColor[4] = {0, 1, 0, 1};\r
345         radQueueClearColor(queue, 0, clearColor);\r
346     }\r
347     {\r
348         radQueueScissor(queue, offscreenWidth/2, offscreenHeight/2, offscreenWidth/2, offscreenHeight/2);\r
349         float clearColor[4] = {0, 0, 1, 1};\r
350         radQueueClearColor(queue, 0, clearColor);\r
351     }\r
352     radQueueScissor(queue, 0, 0, offscreenWidth, offscreenHeight);\r
353     radQueueViewport(queue, 0, 0, offscreenWidth, offscreenHeight);\r
354 \r
355     RADbindGroupElement b[4] = {{vboHandle, 0, ~0}, {vboHandle, sizeof(vertexData), ~0}, {uboHandle, 0, 4*sizeof(float)}, {texHandle, 0, ~0}};\r
356     RADbuffer bindGroup = AllocAndFillBuffer(device, b, sizeof(b), RAD_BINDGROUP_ACCESS_BIT, false);\r
357 \r
358     RADbindGroupHandle bindGroupHandle = radGetBindGroupHandle(bindGroup);\r
359 \r
360     if (useCopyQueue) {\r
361         // Sync from copy queue to graphics queue. Note that we currently don't sync in the \r
362         // opposite direction at the end of the frame, because radQueuePresent effectively\r
363         // does a Finish so it isn't needed.\r
364         RADsync sync = radCreateSync(device);\r
365         radQueueFenceSync(copyQueue, sync, RAD_SYNC_ALL_GPU_COMMANDS_COMPLETE, 0);\r
366         radQueueWaitSync(queue, sync);\r
367         radReleaseSync(sync);\r
368     }\r
369 \r
370     clock_t startTime = clock();\r
371     unsigned int numIterations = benchmark ? 1000000 : 1;\r
372 \r
373     switch (drawMode) {\r
374     case QUEUE:\r
375         for (unsigned int i = 0; i < numIterations; ++i) {\r
376             // Bind the pipeline, bind vertex arrays and textures, and draw\r
377             radQueueBindPipeline(queue, RAD_PIPELINE_TYPE_GRAPHICS, pipelineHandle);\r
378             radQueueBindGroup(queue, RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT, 0, 4, bindGroupHandle, 0);\r
379             //radQueueDrawArrays(queue, RAD_TRIANGLES, 0, 6);\r
380             radQueueDrawElements(queue, RAD_TRIANGLES, RAD_INDEX_UNSIGNED_SHORT, 6, iboHandle, 0);\r
381         }\r
382         break;\r
383     case TOKEN:\r
384         {\r
385             typedef struct Draw {\r
386                 RADuint pipelineHeader;\r
387                 RADtokenBindGraphicsPipeline pipeline;\r
388                 RADuint bindGroupHeader;\r
389                 RADtokenBindGroup bindGroup;\r
390                 RADuint drawElementsHeader;\r
391                 RADtokenDrawElements drawElements;\r
392             } Draw;\r
393             Draw d;\r
394             memset(&d, 0, sizeof(d));\r
395             d.pipelineHeader = radGetTokenHeader(device, RAD_TOKEN_BIND_GRAPHICS_PIPELINE);\r
396             d.pipeline.pipelineHandle = pipelineHandle;\r
397             d.bindGroupHeader = radGetTokenHeader(device, RAD_TOKEN_BIND_GROUP);\r
398             d.bindGroup.stages = RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT;\r
399             d.bindGroup.group = 0;\r
400             d.bindGroup.groupHandle = bindGroupHandle;\r
401             d.bindGroup.offset = 0;\r
402             d.bindGroup.count = 4;\r
403             d.drawElementsHeader = radGetTokenHeader(device, RAD_TOKEN_DRAW_ELEMENTS);\r
404             d.drawElements.indexHandle = iboHandle;\r
405             d.drawElements.mode = RAD_TRIANGLES;\r
406             d.drawElements.type = RAD_INDEX_UNSIGNED_SHORT;\r
407             d.drawElements.count = 6;\r
408             for (unsigned int i = 0; i < numIterations; ++i) {\r
409                 radQueueSubmitDynamic(queue, &d, sizeof(d));\r
410             }\r
411         }\r
412         break;\r
413     case COMMAND:\r
414         {\r
415             RADcommandBuffer cmd = radCreateCommandBuffer(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);\r
416             radCmdBindPipeline(cmd, RAD_PIPELINE_TYPE_GRAPHICS, pipelineHandle);\r
417             radCmdBindGroup(cmd, RAD_VERTEX_SHADER_BIT | RAD_FRAGMENT_SHADER_BIT, 0, 4, bindGroupHandle, 0);\r
418             radCmdDrawElements(cmd, RAD_TRIANGLES, RAD_INDEX_UNSIGNED_SHORT, 6, iboHandle, 0);\r
419             radCompileCommandBuffer(cmd);\r
420             RADcommandHandle cmdHandle = radGetCommandHandle(cmd);\r
421             for (unsigned int i = 0; i < numIterations; ++i) {\r
422                 radQueueSubmitCommands(queue, 1, &cmdHandle);\r
423             }\r
424             radReleaseCommandBuffer(cmd);\r
425         }\r
426         break;\r
427     }\r
428 \r
429     if (benchmark) {\r
430         clock_t currentTime = clock();\r
431         printf("%f\n", 1.0f*numIterations*CLOCKS_PER_SEC/(currentTime - startTime));\r
432     }\r
433     \r
434     radQueueEndPass(queue, pass);\r
435 \r
436     // Kickoff submitted command buffers for the queue\r
437     //radFlushQueue(queue);\r
438 \r
439 #if USE_MULTISAMPLE\r
440     radQueuePresent(queue, tex1x);\r
441 #else\r
442     radQueuePresent(queue, rtTex);\r
443 #endif\r
444 \r
445     radReleaseProgram(pgm);\r
446     radReleaseColorState(color);\r
447     radReleaseDepthStencilState(depth);\r
448     radReleaseVertexState(vertex);\r
449     radReleaseRasterState(raster);\r
450     radReleaseRtFormatState(rtFormat);\r
451     radReleaseBuffer(vbo, RAD_TAG_AUTO);\r
452     radReleaseBuffer(ibo, RAD_TAG_AUTO);\r
453     radReleaseBuffer(pbo, RAD_TAG_AUTO);\r
454     radReleaseBuffer(ubo, RAD_TAG_AUTO);\r
455     radReleaseBuffer(bindGroup, RAD_TAG_AUTO);\r
456     radReleaseTexture(texture, RAD_TAG_AUTO);\r
457     radReleaseTexture(rtTex, RAD_TAG_AUTO);\r
458     radReleaseTexture(depthTex, RAD_TAG_AUTO);\r
459     radReleaseSampler(sampler);\r
460     radReleasePipeline(pipeline);\r
461     radReleasePass(pass);\r
462 #if USE_MULTISAMPLE\r
463     radReleaseTexture(tex1x, RAD_TAG_AUTO);\r
464 #endif\r
465 }\r
466 \r