mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
536 lines
19 KiB
C++
536 lines
19 KiB
C++
//
|
|
// Copyright (c) 2017 The Khronos Group Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
#include "testBase.h"
|
|
|
|
#if defined(__APPLE__)
|
|
#include <OpenGL/glu.h>
|
|
#else
|
|
#include <GL/glu.h>
|
|
#include <CL/cl_gl.h>
|
|
#endif
|
|
|
|
#if defined(__linux__)
|
|
GLboolean gluCheckExtension(const GLubyte *extension, const GLubyte *extensions)
|
|
{
|
|
const GLubyte *start;
|
|
GLubyte *where, *terminator;
|
|
|
|
/* Extension names should not have spaces. */
|
|
where = (GLubyte *)strchr((const char *)extension, ' ');
|
|
if (where || *extension == '\0') return 0;
|
|
/* It takes a bit of care to be fool-proof about parsing the
|
|
OpenGL extensions string. Don't be fooled by sub-strings,
|
|
etc. */
|
|
start = extensions;
|
|
for (;;)
|
|
{
|
|
where = (GLubyte *)strstr((const char *)start, (const char *)extension);
|
|
if (!where) break;
|
|
terminator = where + strlen((const char *)extension);
|
|
if (where == start || *(where - 1) == ' ')
|
|
if (*terminator == ' ' || *terminator == '\0') return 1;
|
|
start = terminator;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
// This is defined in the write common code:
|
|
extern int test_cl_image_write(cl_context context, cl_command_queue queue,
|
|
GLenum target, cl_mem clImage, size_t width,
|
|
size_t height, size_t depth,
|
|
cl_image_format *outFormat,
|
|
ExplicitType *outType, void **outSourceBuffer,
|
|
MTdata d);
|
|
|
|
extern int test_cl_image_read(cl_context context, cl_command_queue queue,
|
|
GLenum gl_target, cl_mem image, size_t width,
|
|
size_t height, size_t depth, size_t sampleNum,
|
|
cl_image_format *outFormat, ExplicitType *outType,
|
|
void **outResultBuffer);
|
|
|
|
|
|
static int test_attach_renderbuffer_read_image(
|
|
cl_context context, cl_command_queue queue, GLenum glTarget,
|
|
GLuint glRenderbuffer, size_t imageWidth, size_t imageHeight,
|
|
cl_image_format *outFormat, ExplicitType *outType, void **outResultBuffer)
|
|
{
|
|
int error;
|
|
|
|
// Create a CL image from the supplied GL renderbuffer
|
|
cl_mem image = (*clCreateFromGLRenderbuffer_ptr)(context, CL_MEM_READ_ONLY,
|
|
glRenderbuffer, &error);
|
|
if (error != CL_SUCCESS)
|
|
{
|
|
print_error(error, "Unable to create CL image from GL renderbuffer");
|
|
return error;
|
|
}
|
|
|
|
return test_cl_image_read(context, queue, glTarget, image, imageWidth,
|
|
imageHeight, 1, 1, outFormat, outType,
|
|
outResultBuffer);
|
|
}
|
|
|
|
int test_renderbuffer_read_image(cl_context context, cl_command_queue queue,
|
|
GLsizei width, GLsizei height,
|
|
GLenum attachment, GLenum format,
|
|
GLenum internalFormat, GLenum glType,
|
|
ExplicitType type, MTdata d)
|
|
{
|
|
int error;
|
|
|
|
if (type == kHalf)
|
|
if (DetectFloatToHalfRoundingMode(queue)) return 1;
|
|
|
|
// Create the GL renderbuffer
|
|
glFramebufferWrapper glFramebuffer;
|
|
glRenderbufferWrapper glRenderbuffer;
|
|
void *tmp = CreateGLRenderbuffer(
|
|
width, height, attachment, format, internalFormat, glType, type,
|
|
&glFramebuffer, &glRenderbuffer, &error, d, true);
|
|
BufferOwningPtr<char> inputBuffer(tmp);
|
|
if (error != 0)
|
|
{
|
|
if ((format == GL_RGBA_INTEGER_EXT)
|
|
&& (!CheckGLIntegerExtensionSupport()))
|
|
{
|
|
log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. "
|
|
"Skipping test.\n");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return error;
|
|
}
|
|
}
|
|
|
|
// Run and get the results
|
|
cl_image_format clFormat;
|
|
ExplicitType actualType;
|
|
char *outBuffer;
|
|
error = test_attach_renderbuffer_read_image(
|
|
context, queue, attachment, glRenderbuffer, width, height, &clFormat,
|
|
&actualType, (void **)&outBuffer);
|
|
if (error != 0) return error;
|
|
BufferOwningPtr<char> actualResults(outBuffer);
|
|
|
|
log_info("- Read [%4d x %4d] : GL renderbuffer : %s : %s : %s => CL Image "
|
|
": %s : %s \n",
|
|
width, height, GetGLFormatName(format),
|
|
GetGLFormatName(internalFormat), GetGLTypeName(glType),
|
|
GetChannelOrderName(clFormat.image_channel_order),
|
|
GetChannelTypeName(clFormat.image_channel_data_type));
|
|
|
|
#ifdef DEBUG
|
|
log_info("- start read GL data -- \n");
|
|
DumpGLBuffer(glType, width, height, actualResults);
|
|
log_info("- end read GL data -- \n");
|
|
#endif
|
|
|
|
// We have to convert our input buffer to the returned type, so we can
|
|
// validate.
|
|
BufferOwningPtr<char> convertedInput(convert_to_expected(
|
|
inputBuffer, width * height, type, actualType,
|
|
get_channel_order_channel_count(clFormat.image_channel_order)));
|
|
|
|
#ifdef DEBUG
|
|
log_info("- start input data -- \n");
|
|
DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height,
|
|
convertedInput);
|
|
log_info("- end input data -- \n");
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
log_info("- start converted data -- \n");
|
|
DumpGLBuffer(GetGLTypeForExplicitType(actualType), width, height,
|
|
actualResults);
|
|
log_info("- end converted data -- \n");
|
|
#endif
|
|
|
|
// Now we validate
|
|
int valid = 0;
|
|
if (convertedInput)
|
|
{
|
|
if (actualType == kFloat)
|
|
valid = validate_float_results(
|
|
convertedInput, actualResults, width, height, 1,
|
|
get_channel_order_channel_count(clFormat.image_channel_order));
|
|
else
|
|
valid = validate_integer_results(
|
|
convertedInput, actualResults, width, height, 1,
|
|
get_explicit_type_size(actualType));
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
int test_renderbuffer_read(cl_device_id device, cl_context context,
|
|
cl_command_queue queue, int numElements)
|
|
{
|
|
GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
|
|
|
|
struct
|
|
{
|
|
GLenum internal;
|
|
GLenum format;
|
|
GLenum datatype;
|
|
ExplicitType type;
|
|
|
|
} formats[] = {
|
|
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
|
|
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
|
|
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
|
|
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
|
|
|
|
// Renderbuffers with integer formats do not seem to work reliably across
|
|
// platforms/implementations. Disabling this in version 1.0 of CL
|
|
// conformance tests.
|
|
|
|
#ifdef TEST_INTEGER_FORMATS
|
|
|
|
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
|
|
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
|
|
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
|
|
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
|
|
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
|
|
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
|
|
#endif
|
|
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
|
|
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
|
|
};
|
|
|
|
size_t fmtIdx, attIdx;
|
|
int error = 0;
|
|
#ifdef DEBUG
|
|
size_t iter = 1;
|
|
#else
|
|
size_t iter = 6;
|
|
#endif
|
|
RandomSeed seed(gRandomSeed);
|
|
|
|
// Check if images are supported
|
|
if (checkForImageSupport(device))
|
|
{
|
|
log_info("Device does not support images. Skipping test.\n");
|
|
return 0;
|
|
}
|
|
|
|
if (!gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object",
|
|
glGetString(GL_EXTENSIONS)))
|
|
{
|
|
log_info("Renderbuffers are not supported by this OpenGL "
|
|
"implementation; skipping test\n");
|
|
return 0;
|
|
}
|
|
|
|
// Loop through a set of GL formats, testing a set of sizes against each one
|
|
for (fmtIdx = 0; fmtIdx < sizeof(formats) / sizeof(formats[0]); fmtIdx++)
|
|
{
|
|
for (attIdx = 0; attIdx < sizeof(attachments) / sizeof(attachments[0]);
|
|
attIdx++)
|
|
{
|
|
size_t i;
|
|
|
|
log_info("Testing renderbuffer read for %s : %s : %s : %s\n",
|
|
GetGLAttachmentName(attachments[attIdx]),
|
|
GetGLFormatName(formats[fmtIdx].internal),
|
|
GetGLBaseFormatName(formats[fmtIdx].format),
|
|
GetGLTypeName(formats[fmtIdx].datatype));
|
|
|
|
for (i = 0; i < iter; i++)
|
|
{
|
|
GLsizei width = random_in_range(16, 512, seed);
|
|
GLsizei height = random_in_range(16, 512, seed);
|
|
#ifdef DEBUG
|
|
width = height = 4;
|
|
#endif
|
|
|
|
if (test_renderbuffer_read_image(
|
|
context, queue, width, height, attachments[attIdx],
|
|
formats[fmtIdx].format, formats[fmtIdx].internal,
|
|
formats[fmtIdx].datatype, formats[fmtIdx].type, seed))
|
|
|
|
{
|
|
log_error("ERROR: Renderbuffer read test failed for %s : "
|
|
"%s : %s : %s\n\n",
|
|
GetGLAttachmentName(attachments[attIdx]),
|
|
GetGLFormatName(formats[fmtIdx].internal),
|
|
GetGLBaseFormatName(formats[fmtIdx].format),
|
|
GetGLTypeName(formats[fmtIdx].datatype));
|
|
|
|
error++;
|
|
break; // Skip other sizes for this combination
|
|
}
|
|
}
|
|
if (i == iter)
|
|
{
|
|
log_info("passed: Renderbuffer read test passed for %s : %s : "
|
|
"%s : %s\n\n",
|
|
GetGLAttachmentName(attachments[attIdx]),
|
|
GetGLFormatName(formats[fmtIdx].internal),
|
|
GetGLBaseFormatName(formats[fmtIdx].format),
|
|
GetGLTypeName(formats[fmtIdx].datatype));
|
|
}
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
#pragma mark -------------------- Write tests -------------------------
|
|
|
|
int test_attach_renderbuffer_write_to_image(
|
|
cl_context context, cl_command_queue queue, GLenum glTarget,
|
|
GLuint glRenderbuffer, size_t imageWidth, size_t imageHeight,
|
|
cl_image_format *outFormat, ExplicitType *outType, MTdata d,
|
|
void **outSourceBuffer)
|
|
{
|
|
int error;
|
|
|
|
// Create a CL image from the supplied GL renderbuffer
|
|
clMemWrapper image = (*clCreateFromGLRenderbuffer_ptr)(
|
|
context, CL_MEM_WRITE_ONLY, glRenderbuffer, &error);
|
|
if (error != CL_SUCCESS)
|
|
{
|
|
print_error(error, "Unable to create CL image from GL renderbuffer");
|
|
return error;
|
|
}
|
|
|
|
return test_cl_image_write(context, queue, glTarget, image, imageWidth,
|
|
imageHeight, 1, outFormat, outType,
|
|
outSourceBuffer, d);
|
|
}
|
|
|
|
int test_renderbuffer_image_write(cl_context context, cl_command_queue queue,
|
|
GLsizei width, GLsizei height,
|
|
GLenum attachment, GLenum format,
|
|
GLenum internalFormat, GLenum glType,
|
|
ExplicitType type, MTdata d)
|
|
{
|
|
int error;
|
|
|
|
if (type == kHalf)
|
|
if (DetectFloatToHalfRoundingMode(queue)) return 1;
|
|
|
|
// Create the GL renderbuffer
|
|
glFramebufferWrapper glFramebuffer;
|
|
glRenderbufferWrapper glRenderbuffer;
|
|
CreateGLRenderbuffer(width, height, attachment, format, internalFormat,
|
|
glType, type, &glFramebuffer, &glRenderbuffer, &error,
|
|
d, false);
|
|
if (error != 0)
|
|
{
|
|
if ((format == GL_RGBA_INTEGER_EXT)
|
|
&& (!CheckGLIntegerExtensionSupport()))
|
|
{
|
|
log_info("OpenGL version does not support GL_RGBA_INTEGER_EXT. "
|
|
"Skipping test.\n");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return error;
|
|
}
|
|
}
|
|
|
|
// Run and get the results
|
|
cl_image_format clFormat;
|
|
ExplicitType sourceType;
|
|
ExplicitType validationType;
|
|
void *outSourceBuffer;
|
|
|
|
error = test_attach_renderbuffer_write_to_image(
|
|
context, queue, attachment, glRenderbuffer, width, height, &clFormat,
|
|
&sourceType, d, (void **)&outSourceBuffer);
|
|
if (error != 0) return error;
|
|
|
|
// If actual source type was half, convert to float for validation.
|
|
if (sourceType == kHalf)
|
|
validationType = kFloat;
|
|
else
|
|
validationType = sourceType;
|
|
|
|
BufferOwningPtr<char> validationSource(convert_to_expected(
|
|
outSourceBuffer, width * height, sourceType, validationType,
|
|
get_channel_order_channel_count(clFormat.image_channel_order)));
|
|
|
|
log_info("- Write [%4d x %4d] : GL Renderbuffer : %s : %s : %s => CL Image "
|
|
": %s : %s \n",
|
|
width, height, GetGLFormatName(format),
|
|
GetGLFormatName(internalFormat), GetGLTypeName(glType),
|
|
GetChannelOrderName(clFormat.image_channel_order),
|
|
GetChannelTypeName(clFormat.image_channel_data_type));
|
|
|
|
// Now read the results from the GL renderbuffer
|
|
BufferOwningPtr<char> resultData(
|
|
ReadGLRenderbuffer(glFramebuffer, glRenderbuffer, attachment, format,
|
|
internalFormat, glType, type, width, height));
|
|
|
|
#ifdef DEBUG
|
|
log_info("- start result data -- \n");
|
|
DumpGLBuffer(glType, width, height, resultData);
|
|
log_info("- end result data -- \n");
|
|
#endif
|
|
|
|
// We have to convert our input buffer to the returned type, so we can
|
|
// validate.
|
|
BufferOwningPtr<char> convertedData(convert_to_expected(
|
|
resultData, width * height, type, validationType,
|
|
get_channel_order_channel_count(clFormat.image_channel_order)));
|
|
|
|
#ifdef DEBUG
|
|
log_info("- start input data -- \n");
|
|
DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height,
|
|
validationSource);
|
|
log_info("- end input data -- \n");
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
log_info("- start converted data -- \n");
|
|
DumpGLBuffer(GetGLTypeForExplicitType(validationType), width, height,
|
|
convertedData);
|
|
log_info("- end converted data -- \n");
|
|
#endif
|
|
|
|
// Now we validate
|
|
int valid = 0;
|
|
if (convertedData)
|
|
{
|
|
if (sourceType == kFloat || sourceType == kHalf)
|
|
valid = validate_float_results(
|
|
validationSource, convertedData, width, height, 1,
|
|
get_channel_order_channel_count(clFormat.image_channel_order));
|
|
else
|
|
valid = validate_integer_results(validationSource, convertedData,
|
|
width, height, 1,
|
|
get_explicit_type_size(type));
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
int test_renderbuffer_write(cl_device_id device, cl_context context,
|
|
cl_command_queue queue, int numElements)
|
|
{
|
|
GLenum attachments[] = { GL_COLOR_ATTACHMENT0_EXT };
|
|
|
|
struct
|
|
{
|
|
GLenum internal;
|
|
GLenum format;
|
|
GLenum datatype;
|
|
ExplicitType type;
|
|
|
|
} formats[] = {
|
|
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
|
|
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, kUChar },
|
|
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, kUChar },
|
|
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, kUShort },
|
|
|
|
// Renderbuffers with integer formats do not seem to work reliably across
|
|
// platforms/implementations. Disabling this in version 1.0 of CL
|
|
// conformance tests.
|
|
|
|
#ifdef TEST_INTEGER_FORMATS
|
|
|
|
{ GL_RGBA8I_EXT, GL_RGBA_INTEGER_EXT, GL_BYTE, kChar },
|
|
{ GL_RGBA16I_EXT, GL_RGBA_INTEGER_EXT, GL_SHORT, kShort },
|
|
{ GL_RGBA32I_EXT, GL_RGBA_INTEGER_EXT, GL_INT, kInt },
|
|
{ GL_RGBA8UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_BYTE, kUChar },
|
|
{ GL_RGBA16UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, kUShort },
|
|
{ GL_RGBA32UI_EXT, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, kUInt },
|
|
#endif
|
|
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, kFloat },
|
|
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, kHalf }
|
|
};
|
|
|
|
size_t fmtIdx, attIdx;
|
|
int error = 0;
|
|
size_t iter = 6;
|
|
#ifdef DEBUG
|
|
iter = 1;
|
|
#endif
|
|
RandomSeed seed(gRandomSeed);
|
|
|
|
// Check if images are supported
|
|
if (checkForImageSupport(device))
|
|
{
|
|
log_info("Device does not support images. Skipping test.\n");
|
|
return 0;
|
|
}
|
|
|
|
if (!gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object",
|
|
glGetString(GL_EXTENSIONS)))
|
|
{
|
|
log_info("Renderbuffers are not supported by this OpenGL "
|
|
"implementation; skipping test\n");
|
|
return 0;
|
|
}
|
|
|
|
// Loop through a set of GL formats, testing a set of sizes against each one
|
|
for (fmtIdx = 0; fmtIdx < sizeof(formats) / sizeof(formats[0]); fmtIdx++)
|
|
{
|
|
for (attIdx = 0; attIdx < sizeof(attachments) / sizeof(attachments[0]);
|
|
attIdx++)
|
|
{
|
|
log_info("Testing Renderbuffer write test for %s : %s : %s : %s\n",
|
|
GetGLAttachmentName(attachments[attIdx]),
|
|
GetGLFormatName(formats[fmtIdx].internal),
|
|
GetGLBaseFormatName(formats[fmtIdx].format),
|
|
GetGLTypeName(formats[fmtIdx].datatype));
|
|
|
|
size_t i;
|
|
for (i = 0; i < iter; i++)
|
|
{
|
|
GLsizei width = random_in_range(16, 512, seed);
|
|
GLsizei height = random_in_range(16, 512, seed);
|
|
#ifdef DEBUG
|
|
width = height = 4;
|
|
#endif
|
|
|
|
if (test_renderbuffer_image_write(
|
|
context, queue, width, height, attachments[attIdx],
|
|
formats[fmtIdx].format, formats[fmtIdx].internal,
|
|
formats[fmtIdx].datatype, formats[fmtIdx].type, seed))
|
|
{
|
|
log_error("ERROR: Renderbuffer write test failed for %s : "
|
|
"%s : %s : %s\n\n",
|
|
GetGLAttachmentName(attachments[attIdx]),
|
|
GetGLFormatName(formats[fmtIdx].internal),
|
|
GetGLBaseFormatName(formats[fmtIdx].format),
|
|
GetGLTypeName(formats[fmtIdx].datatype));
|
|
|
|
error++;
|
|
break; // Skip other sizes for this combination
|
|
}
|
|
}
|
|
if (i == iter)
|
|
{
|
|
log_info("passed: Renderbuffer write test passed for %s : %s : "
|
|
"%s : %s\n\n",
|
|
GetGLAttachmentName(attachments[attIdx]),
|
|
GetGLFormatName(formats[fmtIdx].internal),
|
|
GetGLBaseFormatName(formats[fmtIdx].format),
|
|
GetGLTypeName(formats[fmtIdx].datatype));
|
|
}
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|