3 #include "radfnptrinit.h"
\r
14 #include <RAD/rad.h>
\r
15 #include <EGL/egl.h>
\r
19 bool useCopyQueue = false /*true*/;
\r
22 #define SHADER_SOURCE(source) #source
\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
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
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
48 gl_Position = position * scale;
\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
59 "layout(location = 0) out vec4 color;\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
68 varying highp vec4 ftc;
\r
69 uniform sampler2D tex;
\r
72 gl_FragColor = texture2D(tex, ftc.xy);\n
\r
76 // Two triangles that intersect
\r
77 static RADfloat vertexData[] = {-0.5f, -0.5f, 0.5f,
\r
85 // Simple 0/1 texcoords in rgba8 format (used to be color data)
\r
86 static RADubyte texcoordData[] = {0, 0, 0xFF, 0xFF,
\r
94 int windowWidth = 500, windowHeight = 500;
\r
95 int offscreenWidth = 500, offscreenHeight = 500;
\r
103 DrawMode drawMode = QUEUE /* COMMAND */;
\r
104 bool benchmark = false;
\r
108 // obfuscated string for radGetProcAddress
\r
109 PFNRADGETPROCADDRESSPROC getProc = (PFNRADGETPROCADDRESSPROC)eglGetProcAddress("radGetProcAddress");
\r
110 radLoadProcs(getProc);
\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
122 if (useCopyQueue) {
\r
123 radReleaseQueue(copyQueue);
\r
125 radReleaseQueue(queue);
\r
126 radReleaseDevice(device);
\r
129 #define USE_MULTISAMPLE 0
\r
131 RADbuffer AllocAndFillBuffer(RADdevice device, void *data, int sizeofdata, RADbitfield access, bool 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
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
146 radQueueCopyBuffer(useCopyQueue ? copyQueue : queue, tempbo, 0, buffer, 0, sizeofdata);
\r
148 radReleaseBuffer(tempbo, RAD_TAG_AUTO);
\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
163 // Create programs from the device, provide them shader code and compile/link them
\r
164 RADprogram pgm = radCreateProgram(device);
\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
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
179 radRtFormatColorFormat(rtFormat, 0, RAD_RGBA8);
\r
180 radRtFormatDepthFormat(rtFormat, RAD_DEPTH24_STENCIL8);
\r
182 radDepthStencilDepthTestEnable(depth, RAD_TRUE);
\r
183 radDepthStencilDepthWriteEnable(depth, RAD_TRUE);
\r
184 radDepthStencilDepthFunc(depth, RAD_DEPTH_FUNC_LESS);
\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
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
197 // Set the state vector to use two vertex attributes.
\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
213 // Create a pipeline.
\r
214 RADpipeline pipeline = radCreatePipeline(device, RAD_PIPELINE_TYPE_GRAPHICS);
\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
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
236 // Get a handle to be used for setting the buffer as a vertex buffer
\r
237 RADvertexHandle vboHandle = radGetVertexHandle(vbo);
\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
243 // Get a handle to be used for setting the buffer as an index buffer
\r
244 RADvertexHandle iboHandle = radGetVertexHandle(ibo);
\r
246 float scale = 1.5f;
\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
253 // Get a handle to be used for setting the buffer as a uniform buffer
\r
254 RADuniformHandle uboHandle = radGetUniformHandle(ubo);
\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
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
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
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
273 radRasterSamples(raster, 4);
\r
274 radRtFormatColorSamples(rtFormat, 4);
\r
275 radRtFormatDepthStencilSamples(rtFormat, 4);
\r
277 RADpass pass = radCreatePass(device);
\r
278 radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);
\r
279 radPassResolve(pass, RAD_RT_ATTACHMENT_COLOR0, tex1x);
\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
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
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
293 RADpass pass = radCreatePass(device);
\r
294 radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);
\r
297 radCompilePass(pass);
\r
299 radCompilePipeline(pipeline);
\r
300 RADpipelineHandle pipelineHandle = radGetPipelineHandle(pipeline);
\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
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
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
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
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
333 radQueueBeginPass(queue, pass);
\r
335 // Some scissored clears
\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
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
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
352 radQueueScissor(queue, 0, 0, offscreenWidth, offscreenHeight);
\r
353 radQueueViewport(queue, 0, 0, offscreenWidth, offscreenHeight);
\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
358 RADbindGroupHandle bindGroupHandle = radGetBindGroupHandle(bindGroup);
\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
370 clock_t startTime = clock();
\r
371 unsigned int numIterations = benchmark ? 1000000 : 1;
\r
373 switch (drawMode) {
\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
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
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
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
424 radReleaseCommandBuffer(cmd);
\r
430 clock_t currentTime = clock();
\r
431 printf("%f\n", 1.0f*numIterations*CLOCKS_PER_SEC/(currentTime - startTime));
\r
434 radQueueEndPass(queue, pass);
\r
436 // Kickoff submitted command buffers for the queue
\r
437 //radFlushQueue(queue);
\r
439 #if USE_MULTISAMPLE
\r
440 radQueuePresent(queue, tex1x);
\r
442 radQueuePresent(queue, rtTex);
\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