OSDN Git Service

8e2dde9e5bcd40254d7eab298459a3e6386a340b
[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 = true;\r
20 RADqueue copyQueue;\r
21 \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
28     "    vec4 scale;\n"\r
29     "};\n"\r
30     "out vec4 ftc;\n"\r
31     "void main() {\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
37     "  }\n"\r
38     "  ftc = tc;\n"\r
39     "}\n";\r
40 \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
46     "    vec4 scale;\n"\r
47     "};\n"\r
48     "layout(location = 0) out vec4 color;\n"\r
49     "in vec4 ftc;\n"\r
50     "void main() {\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
54     "  }\n"\r
55     "}\n";\r
56 \r
57 \r
58 // Two triangles that intersect\r
59 static RADfloat vertexData[] = {-0.5f, -0.5f, 0.5f, \r
60                                 0.5f, -0.5f,  0.5f,\r
61                                 -0.5f, 0.5f,  0.5f,\r
62 \r
63                                 0.5f, -0.5f, 0.5f,\r
64                                 -0.5f, -0.5f, 0.3f,\r
65                                 0.5f, 0.5f, 0.9f};\r
66 \r
67 // Simple 0/1 texcoords in rgba8 format (used to be color data)\r
68 static RADubyte texcoordData[] = {0, 0, 0xFF, 0xFF,\r
69                                   0xFF, 0, 0, 0xFF,\r
70                                   0, 0xFF, 0, 0xFF,\r
71 \r
72                                   0, 0, 0xFF, 0xFF,\r
73                                   0xFF, 0, 0, 0xFF,\r
74                                   0, 0xFF, 0, 0xFF};\r
75 \r
76 int windowWidth = 500, windowHeight = 500;\r
77 int offscreenWidth = 100, offscreenHeight = 100;\r
78 \r
79 typedef enum {\r
80     QUEUE,\r
81     TOKEN,\r
82     COMMAND,\r
83 } DrawMode;\r
84 \r
85 DrawMode drawMode = COMMAND;\r
86 bool benchmark = false;\r
87 \r
88 void InitRAD()\r
89 {\r
90     // obfuscated string for radGetProcAddress\r
91         PFNRADGETPROCADDRESSPROC getProc = (PFNRADGETPROCADDRESSPROC)eglGetProcAddress("radGetProcAddress");\r
92     radLoadProcs(getProc);\r
93 \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
97     if (useCopyQueue) {\r
98         copyQueue = radCreateQueue(device, RAD_QUEUE_TYPE_GRAPHICS_AND_COMPUTE);\r
99     }\r
100 }\r
101 \r
102 #define USE_MULTISAMPLE 1\r
103 \r
104 RADbuffer AllocAndFillBuffer(RADdevice device, void *data, int sizeofdata, RADbitfield access, bool useCopy)\r
105 {\r
106     if (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
113 \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
118 \r
119         radQueueCopyBuffer(useCopyQueue ? copyQueue : queue, tempbo, 0, buffer, 0, sizeofdata);\r
120 \r
121         radReleaseBuffer(tempbo, RAD_TAG_AUTO);\r
122         return buffer;\r
123     } else {\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
130         return buffer;\r
131     }\r
132 }\r
133 \r
134 void TestRAD()\r
135 {\r
136     // Create programs from the device, provide them shader code and compile/link them\r
137     RADprogram pgm = radCreateProgram(device);\r
138 \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
143 \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
150 \r
151 \r
152     radRtFormatColorFormat(rtFormat, 0, RAD_RGBA8);\r
153     radRtFormatDepthFormat(rtFormat, RAD_DEPTH24_STENCIL8);\r
154 \r
155     radDepthStencilDepthTestEnable(depth, RAD_TRUE);\r
156     radDepthStencilDepthWriteEnable(depth, RAD_TRUE);\r
157     radDepthStencilDepthFunc(depth, RAD_DEPTH_FUNC_LESS);\r
158 \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
163 \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
169 \r
170     // Set the state vector to use two vertex attributes.\r
171     //\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
185 \r
186     // Create a pipeline.\r
187     RADpipeline pipeline = radCreatePipeline(device, RAD_PIPELINE_TYPE_GRAPHICS);\r
188 \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
197 \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
208 \r
209     // Get a handle to be used for setting the buffer as a vertex buffer\r
210     RADvertexHandle vboHandle = radGetVertexHandle(vbo);\r
211 \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
215 \r
216     // Get a handle to be used for setting the buffer as an index buffer\r
217     RADvertexHandle iboHandle = radGetVertexHandle(ibo);\r
218 \r
219     float scale = 1.5f;\r
220     if (benchmark) {\r
221         scale = 0.2f;\r
222     }\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
225 \r
226     // Get a handle to be used for setting the buffer as a uniform buffer\r
227     RADuniformHandle uboHandle = radGetUniformHandle(ubo);\r
228 \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
233 \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
237 \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
241 \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
245 \r
246     radRasterSamples(raster, 4);\r
247     radRtFormatColorSamples(rtFormat, 4);\r
248     radRtFormatDepthStencilSamples(rtFormat, 4);\r
249 \r
250     RADpass pass = radCreatePass(device);\r
251     radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);\r
252     radPassResolve(pass, RAD_RT_ATTACHMENT_COLOR0, tex1x);\r
253 #else\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
257 \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
261 \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
265 \r
266     RADpass pass = radCreatePass(device);\r
267     radPassRenderTargets(pass, 1, &rtHandle, depthHandle, 0);\r
268 #endif\r
269 \r
270     radCompilePass(pass);\r
271 \r
272     radCompilePipeline(pipeline);\r
273     RADpipelineHandle pipelineHandle = radGetPipelineHandle(pipeline);\r
274 \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
278 \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
285 \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
290 \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
299         }\r
300     }\r
301 \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
305 \r
306     radQueueBeginPass(queue, pass);\r
307 \r
308     // Some scissored clears\r
309     {\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
314     }\r
315     {\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
319     }\r
320     {\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
324     }\r
325     radQueueScissor(queue, 0, 0, offscreenWidth, offscreenHeight);\r
326     radQueueViewport(queue, 0, 0, offscreenWidth, offscreenHeight);\r
327 \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
330 \r
331     RADbindGroupHandle bindGroupHandle = radGetBindGroupHandle(bindGroup);\r
332 \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
341     }\r
342 \r
343     clock_t startTime = clock();\r
344     unsigned int numIterations = benchmark ? 1000000 : 1;\r
345 \r
346     switch (drawMode) {\r
347     case QUEUE:\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
354         }\r
355         break;\r
356     case TOKEN:\r
357         {\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
365             } Draw;\r
366             Draw d;\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
383             }\r
384         }\r
385         break;\r
386     case COMMAND:\r
387         {\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
396             }\r
397             radReleaseCommandBuffer(cmd);\r
398         }\r
399         break;\r
400     }\r
401 \r
402     if (benchmark) {\r
403         clock_t currentTime = clock();\r
404         printf("%f\n", 1.0f*numIterations*CLOCKS_PER_SEC/(currentTime - startTime));\r
405     }\r
406     \r
407     radQueueEndPass(queue, pass);\r
408 \r
409     // Kickoff submitted command buffers for the queue\r
410     //radFlushQueue(queue);\r
411 \r
412 #if USE_MULTISAMPLE\r
413     radQueuePresent(queue, tex1x);\r
414 #else\r
415     radQueuePresent(queue, rtTex);\r
416 #endif\r
417 \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
437 #endif\r
438 }\r
439 \r