| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2016 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. |
| * |
| */ /*! |
| * \file |
| * \brief |
| */ /*-------------------------------------------------------------------*/ |
| |
| /** |
| */ /*! |
| * \file gl4cSparseTexture2Tests.cpp |
| * \brief Conformance tests for the GL_ARB_sparse_texture2 functionality. |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "gl4cSparseTexture2Tests.hpp" |
| #include "deStringUtil.hpp" |
| #include "gl4cSparseTextureTests.hpp" |
| #include "gluContextInfo.hpp" |
| #include "gluDefs.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include <cmath> |
| #include <stdio.h> |
| #include <string.h> |
| #include <vector> |
| |
| using namespace glw; |
| using namespace glu; |
| |
| namespace gl4cts |
| { |
| |
| const char* st2_compute_textureFill = "#version 430 core\n" |
| "\n" |
| "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" |
| "\n" |
| "layout (location = 1) writeonly uniform highp <INPUT_TYPE> uni_image;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " <POINT_TYPE> point = <POINT_TYPE>(<POINT_DEF>);\n" |
| " memoryBarrier();\n" |
| " <RETURN_TYPE> color = <RETURN_TYPE><RESULT_EXPECTED>;\n" |
| " imageStore(uni_image, point<SAMPLE_DEF>, color);\n" |
| "}\n"; |
| |
| const char* st2_compute_textureVerify = "#version 430 core\n" |
| "\n" |
| "#extension GL_ARB_sparse_texture2 : enable\n" |
| "\n" |
| "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" |
| "\n" |
| "layout (location = 1, r8ui) writeonly uniform <OUTPUT_TYPE> uni_out_image;\n" |
| "layout (location = 2, <FORMAT>) readonly uniform <INPUT_TYPE> uni_in_image;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " <POINT_TYPE> point = <POINT_TYPE>(<POINT_DEF>);\n" |
| " memoryBarrier();\n" |
| " highp <RETURN_TYPE> color,\n" |
| " expected,\n" |
| " epsilon;\n" |
| " color = imageLoad(uni_in_image, point<SAMPLE_DEF>);\n" |
| " expected = <RETURN_TYPE><RESULT_EXPECTED>;\n" |
| " epsilon = <RETURN_TYPE>(<EPSILON>);\n" |
| "\n" |
| " if (all(lessThanEqual(color, expected + epsilon)) &&\n" |
| " all(greaterThanEqual(color, expected - epsilon)))\n" |
| " {\n" |
| " imageStore(uni_out_image, point, uvec4(255));\n" |
| " }\n" |
| " else {\n" |
| " imageStore(uni_out_image, point, uvec4(0));\n" |
| " }\n" |
| "}\n"; |
| |
| const char* st2_compute_atomicVerify = "#version 430 core\n" |
| "\n" |
| "#extension GL_ARB_sparse_texture2 : enable\n" |
| "\n" |
| "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" |
| "\n" |
| "layout (location = 1, r8ui) writeonly uniform <OUTPUT_TYPE> uni_out_image;\n" |
| "layout (location = 2, <FORMAT>) uniform <INPUT_TYPE> uni_in_image;\n" |
| "\n" |
| "layout (location = 3) uniform int widthCommitted;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " <POINT_TYPE> point,\n" |
| " offset;\n" |
| " point = <POINT_TYPE>(<POINT_DEF>);\n" |
| " offset = <POINT_TYPE>(0);\n" |
| " offset.x = widthCommitted;\n" |
| " memoryBarrier();\n" |
| " if (point.x >= widthCommitted) {\n" |
| " uint index = ((point.x - widthCommitted) + point.y * 8) % 8;\n" |
| " <DATA_TYPE> value = 127;\n" |
| " if (index == 0)\n" |
| " value = imageAtomicExchange(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| " else if (index == 1)\n" |
| " value = imageAtomicCompSwap(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0), <DATA_TYPE>(0x0F));\n" |
| " else if (index == 2)\n" |
| " value = imageAtomicAdd(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| " else if (index == 3)\n" |
| " value = imageAtomicAnd(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| " else if (index == 4)\n" |
| " value = imageAtomicOr(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| " else if (index == 5)\n" |
| " value = imageAtomicXor(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| " else if (index == 6)\n" |
| " value = imageAtomicMin(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| " else if (index == 7)\n" |
| " value = imageAtomicMax(uni_in_image, point<SAMPLE_DEF>,\n" |
| " <DATA_TYPE>(0x0F));\n" |
| "\n" |
| " <RETURN_TYPE> color = imageLoad(uni_in_image, point<SAMPLE_DEF>);\n" |
| "\n" |
| " if (value == 0)\n" |
| " imageStore(uni_out_image, point - offset, uvec4(0));\n" |
| " else\n" |
| " imageStore(uni_out_image, point - offset, uvec4(value));\n" |
| "\n" |
| " if (color.r == 0)\n" |
| " imageStore(uni_out_image, point, uvec4(0));\n" |
| " else\n" |
| " imageStore(uni_out_image, point, uvec4(1));\n" |
| " }\n" |
| "}\n"; |
| |
| const char* st2_vertex_drawBuffer = "#version 430 core\n" |
| "\n" |
| "#extension GL_ARB_sparse_texture2 : enable\n" |
| "\n" |
| "in vec3 vertex;\n" |
| "in vec2 inTexCoord;\n" |
| "out vec2 texCoord;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " texCoord = inTexCoord;\n" |
| " gl_Position = vec4(vertex, 1);\n" |
| "}\n"; |
| |
| const char* st2_fragment_drawBuffer = "#version 430 core\n" |
| "\n" |
| "#extension GL_ARB_sparse_texture2 : enable\n" |
| "\n" |
| "layout (location = 1) uniform sampler2D uni_sampler;\n" |
| "\n" |
| "in vec2 texCoord;\n" |
| "out vec4 fragColor;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " fragColor = texture(uni_sampler, texCoord);\n" |
| "}\n"; |
| |
| const char* st2_compute_extensionCheck = "#version 450 core\n" |
| "\n" |
| "#extension <EXTENSION> : require\n" |
| "\n" |
| "#ifndef <EXTENSION>\n" |
| " #error <EXTENSION> not defined\n" |
| "#else\n" |
| " #if (<EXTENSION> != 1)\n" |
| " #error <EXTENSION> wrong value\n" |
| " #endif\n" |
| "#endif // <EXTENSION>\n" |
| "\n" |
| "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "}\n"; |
| |
| const char* st2_compute_lookupVerify = "#version 450 core\n" |
| "\n" |
| "#extension GL_ARB_sparse_texture2 : enable\n" |
| "#extension GL_ARB_sparse_texture_clamp : enable\n" |
| "\n" |
| "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" |
| "\n" |
| "layout (location = 1, r8ui) writeonly uniform <OUTPUT_TYPE> uni_out;\n" |
| "layout (location = 2<FORMAT_DEF>) uniform <INPUT_TYPE> uni_in;\n" |
| "layout (location = 3) uniform int widthCommitted;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " <POINT_TYPE> point = <POINT_TYPE>(<POINT_DEF>);\n" |
| " <ICOORD_TYPE> texSize = <ICOORD_TYPE>(<SIZE_DEF>);\n" |
| " <ICOORD_TYPE> icoord = <ICOORD_TYPE>(<COORD_DEF>);\n" |
| " <COORD_TYPE> coord = <COORD_TYPE>(<COORD_DEF>) / <COORD_TYPE>(texSize);\n" |
| " <RETURN_TYPE> retValue,\n" |
| " expValue,\n" |
| " epsilon;\n" |
| " retValue = <RETURN_TYPE>(0);\n" |
| " expValue = <RETURN_TYPE><RESULT_EXPECTED>;\n" |
| " epsilon = <RETURN_TYPE>(<EPSILON>);\n" |
| "\n" |
| "<CUBE_MAP_COORD_DEF>\n" |
| "<OFFSET_ARRAY_DEF>\n" |
| "\n" |
| " ivec2 corner1 = ivec2(1, 1);\n" |
| " ivec2 corner2 = ivec2(texSize.x - 1, texSize.y - 1);\n" |
| "\n" |
| " int code = <FUNCTION>(uni_in,\n" |
| " <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n" |
| " retValue<COMPONENT_DEF>);\n" |
| " memoryBarrier();\n" |
| "\n" |
| " imageStore(uni_out, point, uvec4(255));\n" |
| "\n" |
| " if (point.x > corner1.x && point.y > corner1.y &&\n" |
| " point.x < corner2.x && point.y < corner2.y &&\n" |
| " point.x < widthCommitted - 1)\n" |
| " {\n" |
| " if (!sparseTexelsResidentARB(code) ||\n" |
| " any(greaterThan(retValue, expValue + epsilon)) ||\n" |
| " any(lessThan(retValue, expValue - epsilon)))\n" |
| " {\n" |
| " imageStore(uni_out, point, uvec4(0));\n" |
| " }\n" |
| " }\n" |
| "\n" |
| " if (point.x > corner1.x && point.y > corner1.y &&\n" |
| " point.x < corner2.x && point.y < corner2.y &&\n" |
| " point.x >= widthCommitted + 1)\n" |
| " {\n" |
| " if (sparseTexelsResidentARB(code))\n" |
| " {\n" |
| " imageStore(uni_out, point, uvec4(0));\n" |
| " }\n" |
| " }\n" |
| "}\n"; |
| |
| /** Replace all occurance of <token> with <text> in <string> |
| * |
| * @param token Token string |
| * @param text String that will be used as replacement for <token> |
| * @param string String to work on |
| **/ |
| void replaceToken(const GLchar* token, const GLchar* text, std::string& string) |
| { |
| const size_t text_length = strlen(text); |
| const size_t token_length = strlen(token); |
| |
| size_t token_position; |
| while ((token_position = string.find(token, 0)) != std::string::npos) |
| { |
| string.replace(token_position, token_length, text, text_length); |
| } |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| ShaderExtensionTestCase::ShaderExtensionTestCase(deqp::Context& context, const std::string extension) |
| : TestCase(context, "ShaderExtension", "Verifies if extension is available for GLSL"), mExtension(extension) |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult ShaderExtensionTestCase::iterate() |
| { |
| if (!m_context.getContextInfo().isExtensionSupported(mExtension.c_str())) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| return STOP; |
| } |
| |
| const Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| std::string shader = st2_compute_extensionCheck; |
| replaceToken("<EXTENSION>", mExtension.c_str(), shader); |
| |
| ProgramSources sources; |
| sources << ComputeSource(shader); |
| ShaderProgram program(gl, sources); |
| |
| if (!program.isOk()) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| m_testCtx.getLog() << tcu::TestLog::Message << "Checking shader preprocessor directives failed. Source:\n" |
| << shader.c_str() << "InfoLog:\n" |
| << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog << "\n" |
| << tcu::TestLog::EndMessage; |
| return STOP; |
| } |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| StandardPageSizesTestCase::StandardPageSizesTestCase(deqp::Context& context) |
| : TestCase(context, "StandardPageSizesTestCase", |
| "Verifies if values returned by GetInternalFormativ query matches Standard Virtual Page Sizes") |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Stub init method */ |
| void StandardPageSizesTestCase::init() |
| { |
| mSupportedTargets.push_back(GL_TEXTURE_1D); |
| mSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY); |
| mSupportedTargets.push_back(GL_TEXTURE_2D); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_ARRAY); |
| mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP); |
| mSupportedTargets.push_back(GL_TEXTURE_CUBE_MAP_ARRAY); |
| mSupportedTargets.push_back(GL_TEXTURE_RECTANGLE); |
| mSupportedTargets.push_back(GL_TEXTURE_BUFFER); |
| mSupportedTargets.push_back(GL_RENDERBUFFER); |
| |
| mStandardVirtualPageSizesTable[GL_R8] = PageSizeStruct(256, 256, 1); |
| mStandardVirtualPageSizesTable[GL_R8_SNORM] = PageSizeStruct(256, 256, 1); |
| mStandardVirtualPageSizesTable[GL_R8I] = PageSizeStruct(256, 256, 1); |
| mStandardVirtualPageSizesTable[GL_R8UI] = PageSizeStruct(256, 256, 1); |
| mStandardVirtualPageSizesTable[GL_R16] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R16_SNORM] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG8] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG8_SNORM] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGB565] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R16F] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R16I] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R16UI] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG8I] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG8UI] = PageSizeStruct(256, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG16] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG16_SNORM] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA8] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA8_SNORM] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGB10_A2] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGB10_A2UI] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG16F] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R32F] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R11F_G11F_B10F] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGB9_E5] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R32I] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_R32UI] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG16I] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RG16UI] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA8I] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA8UI] = PageSizeStruct(128, 128, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA16] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA16_SNORM] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA16F] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RG32F] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RG32I] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RG32UI] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA16I] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA16UI] = PageSizeStruct(128, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA32F] = PageSizeStruct(64, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA32I] = PageSizeStruct(64, 64, 1); |
| mStandardVirtualPageSizesTable[GL_RGBA32UI] = PageSizeStruct(64, 64, 1); |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult StandardPageSizesTestCase::iterate() |
| { |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2")) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| return STOP; |
| } |
| |
| const Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message << "Testing getInternalformativ" << tcu::TestLog::EndMessage; |
| |
| for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end(); |
| ++iter) |
| { |
| const GLint& target = *iter; |
| |
| for (std::map<glw::GLint, PageSizeStruct>::const_iterator formIter = mStandardVirtualPageSizesTable.begin(); |
| formIter != mStandardVirtualPageSizesTable.end(); ++formIter) |
| { |
| const PageSizePair& format = *formIter; |
| const PageSizeStruct& page = format.second; |
| |
| GLint pageSizeX; |
| GLint pageSizeY; |
| GLint pageSizeZ; |
| SparseTextureUtils::getTexturePageSizes(gl, target, format.first, pageSizeX, pageSizeY, pageSizeZ); |
| |
| if (pageSizeX != page.xSize || pageSizeY != page.ySize || pageSizeZ != page.zSize) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Standard Virtual Page Size mismatch, target: " << target |
| << ", format: " << format.first << ", returned: " << pageSizeX << "/" << pageSizeY |
| << "/" << pageSizeZ << ", expected: " << page.xSize << "/" << page.ySize << "/" |
| << page.zSize << tcu::TestLog::EndMessage; |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| return STOP; |
| } |
| } |
| } |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| SparseTexture2AllocationTestCase::SparseTexture2AllocationTestCase(deqp::Context& context) |
| : SparseTextureAllocationTestCase(context, "SparseTexture2Allocation", |
| "Verifies TexStorage* functionality added in CTS_ARB_sparse_texture2") |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Initializes the test group contents. */ |
| void SparseTexture2AllocationTestCase::init() |
| { |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| |
| mFullArrayTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| |
| mSupportedInternalFormats.push_back(GL_R8); |
| mSupportedInternalFormats.push_back(GL_R8_SNORM); |
| mSupportedInternalFormats.push_back(GL_R16); |
| mSupportedInternalFormats.push_back(GL_R16_SNORM); |
| mSupportedInternalFormats.push_back(GL_RG8); |
| mSupportedInternalFormats.push_back(GL_RG8_SNORM); |
| mSupportedInternalFormats.push_back(GL_RG16); |
| mSupportedInternalFormats.push_back(GL_RG16_SNORM); |
| mSupportedInternalFormats.push_back(GL_RGB565); |
| mSupportedInternalFormats.push_back(GL_RGBA8); |
| mSupportedInternalFormats.push_back(GL_RGBA8_SNORM); |
| mSupportedInternalFormats.push_back(GL_RGB10_A2); |
| mSupportedInternalFormats.push_back(GL_RGB10_A2UI); |
| mSupportedInternalFormats.push_back(GL_RGBA16); |
| mSupportedInternalFormats.push_back(GL_RGBA16_SNORM); |
| mSupportedInternalFormats.push_back(GL_R16F); |
| mSupportedInternalFormats.push_back(GL_RG16F); |
| mSupportedInternalFormats.push_back(GL_RGBA16F); |
| mSupportedInternalFormats.push_back(GL_R32F); |
| mSupportedInternalFormats.push_back(GL_RG32F); |
| mSupportedInternalFormats.push_back(GL_RGBA32F); |
| mSupportedInternalFormats.push_back(GL_R11F_G11F_B10F); |
| // RGB9_E5 isn't color renderable, and thus isn't valid for multisample |
| // textures. |
| //mSupportedInternalFormats.push_back(GL_RGB9_E5); |
| mSupportedInternalFormats.push_back(GL_R8I); |
| mSupportedInternalFormats.push_back(GL_R8UI); |
| mSupportedInternalFormats.push_back(GL_R16I); |
| mSupportedInternalFormats.push_back(GL_R16UI); |
| mSupportedInternalFormats.push_back(GL_R32I); |
| mSupportedInternalFormats.push_back(GL_R32UI); |
| mSupportedInternalFormats.push_back(GL_RG8I); |
| mSupportedInternalFormats.push_back(GL_RG8UI); |
| mSupportedInternalFormats.push_back(GL_RG16I); |
| mSupportedInternalFormats.push_back(GL_RG16UI); |
| mSupportedInternalFormats.push_back(GL_RG32I); |
| mSupportedInternalFormats.push_back(GL_RG32UI); |
| mSupportedInternalFormats.push_back(GL_RGBA8I); |
| mSupportedInternalFormats.push_back(GL_RGBA8UI); |
| mSupportedInternalFormats.push_back(GL_RGBA16I); |
| mSupportedInternalFormats.push_back(GL_RGBA16UI); |
| mSupportedInternalFormats.push_back(GL_RGBA32I); |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult SparseTexture2AllocationTestCase::iterate() |
| { |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2")) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| return STOP; |
| } |
| |
| return SparseTextureAllocationTestCase::iterate(); |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| SparseTexture2CommitmentTestCase::SparseTexture2CommitmentTestCase(deqp::Context& context, const char* name, |
| const char* description) |
| : SparseTextureCommitmentTestCase(context, name, description) |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| SparseTexture2CommitmentTestCase::SparseTexture2CommitmentTestCase(deqp::Context& context) |
| : SparseTextureCommitmentTestCase( |
| context, "SparseTexture2Commitment", |
| "Verifies glTexPageCommitmentARB functionality added by ARB_sparse_texture2 extension") |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Initializes the test group contents. */ |
| void SparseTexture2CommitmentTestCase::init() |
| { |
| SparseTextureCommitmentTestCase::init(); |
| |
| //Verify all targets once again and multisample targets as it was added in ARB_sparse_texture2 extension |
| mSupportedTargets.clear(); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult SparseTexture2CommitmentTestCase::iterate() |
| { |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2")) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| return STOP; |
| } |
| |
| return SparseTextureCommitmentTestCase::iterate(); |
| } |
| |
| /** Create set of token strings fit to texture verifying shader |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param sample Texture sample number |
| |
| * @return target Structure of token strings |
| */ |
| SparseTexture2CommitmentTestCase::TokenStrings SparseTexture2CommitmentTestCase::createShaderTokens( |
| GLint target, GLint format, GLint sample, const std::string outputBase, const std::string inputBase) |
| { |
| TokenStrings s; |
| std::string prefix; |
| |
| if (format == GL_R8) |
| { |
| s.format = "r8"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_R8_SNORM) |
| { |
| s.format = "r8_snorm"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_R16) |
| { |
| s.format = "r16"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_R16_SNORM) |
| { |
| s.format = "r16_snorm"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RG8) |
| { |
| s.format = "rg8"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RG8_SNORM) |
| { |
| s.format = "rg8_snorm"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RG16) |
| { |
| s.format = "rg16"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RG16_SNORM) |
| { |
| s.format = "rg16_snorm"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RGBA8) |
| { |
| s.format = "rgba8"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_RGBA8_SNORM) |
| { |
| s.format = "rgba8_snorm"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_RGB10_A2) |
| { |
| s.format = "rgb10_a2"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_RGB10_A2UI) |
| { |
| s.format = "rgb10_a2ui"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RGBA16) |
| { |
| s.format = "rgba16"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_RGBA16_SNORM) |
| { |
| s.format = "rgba16_snorm"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_R16F) |
| { |
| s.format = "r16f"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RG16F) |
| { |
| s.format = "rg16f"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RGBA16F) |
| { |
| s.format = "rgba16f"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_R32F) |
| { |
| s.format = "r32f"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RG32F) |
| { |
| s.format = "rg32f"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_RGBA32F) |
| { |
| s.format = "rgba32f"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| else if (format == GL_R11F_G11F_B10F) |
| { |
| s.format = "r11f_g11f_b10f"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| } |
| else if (format == GL_R8I) |
| { |
| s.format = "r8i"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "i"; |
| } |
| else if (format == GL_R8UI) |
| { |
| s.format = "r8ui"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "u"; |
| } |
| else if (format == GL_R16I) |
| { |
| s.format = "r16i"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "i"; |
| } |
| else if (format == GL_R16UI) |
| { |
| s.format = "r16ui"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "u"; |
| } |
| else if (format == GL_R32I) |
| { |
| s.format = "r32i"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "i"; |
| } |
| else if (format == GL_R32UI) |
| { |
| s.format = "r32ui"; |
| s.resultExpected = "(1, 0, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RG8I) |
| { |
| s.format = "rg8i"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "i"; |
| } |
| else if (format == GL_RG8UI) |
| { |
| s.format = "rg8ui"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RG16I) |
| { |
| s.format = "rg16i"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "i"; |
| } |
| else if (format == GL_RG16UI) |
| { |
| s.format = "rg16ui"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RG32I) |
| { |
| s.format = "rg32i"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "i"; |
| } |
| else if (format == GL_RG32UI) |
| { |
| s.format = "rg32ui"; |
| s.resultExpected = "(1, 1, 0, 1)"; |
| s.resultDefault = "(0, 0, 0, 1)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RGBA8I) |
| { |
| s.format = "rgba8i"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| prefix = "i"; |
| } |
| else if (format == GL_RGBA8UI) |
| { |
| s.format = "rgba8ui"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RGBA16I) |
| { |
| s.format = "rgba16i"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| prefix = "i"; |
| } |
| else if (format == GL_RGBA16UI) |
| { |
| s.format = "rgba16ui"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| prefix = "u"; |
| } |
| else if (format == GL_RGBA32I) |
| { |
| s.format = "rgba32i"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| prefix = "i"; |
| } |
| else if (format == GL_DEPTH_COMPONENT16) |
| { |
| s.format = "r16"; |
| s.resultExpected = "(1, 0, 0, 0)"; |
| s.resultDefault = "(0, 0, 0, 0)"; |
| } |
| |
| s.returnType = prefix + "vec4"; |
| s.outputType = "u" + outputBase + "2D"; |
| s.inputType = prefix + inputBase + "2D"; |
| s.pointType = "ivec2"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.y"; |
| |
| if (s.returnType == "vec4") |
| s.epsilon = "0.008"; |
| else |
| s.epsilon = "0"; |
| |
| if (target == GL_TEXTURE_1D) |
| { |
| s.outputType = "u" + outputBase + "2D"; |
| s.inputType = prefix + inputBase + "1D"; |
| s.pointType = "int"; |
| s.pointDef = "gl_WorkGroupID.x"; |
| } |
| else if (target == GL_TEXTURE_1D_ARRAY) |
| { |
| s.outputType = "u" + outputBase + "2D_ARRAY"; |
| s.inputType = prefix + inputBase + "1DArray"; |
| s.pointType = "ivec2"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.z"; |
| } |
| else if (target == GL_TEXTURE_2D_ARRAY) |
| { |
| s.outputType = "u" + outputBase + "2DArray"; |
| s.inputType = prefix + inputBase + "2DArray"; |
| s.pointType = "ivec3"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.y, gl_WorkGroupID.z"; |
| } |
| else if (target == GL_TEXTURE_3D) |
| { |
| s.outputType = "u" + outputBase + "2DArray"; |
| s.inputType = prefix + inputBase + "3D"; |
| s.pointType = "ivec3"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.y, gl_WorkGroupID.z"; |
| } |
| else if (target == GL_TEXTURE_CUBE_MAP) |
| { |
| s.outputType = "u" + outputBase + "2DArray"; |
| s.inputType = prefix + inputBase + "Cube"; |
| s.pointType = "ivec3"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.y, gl_WorkGroupID.z % 6"; |
| } |
| else if (target == GL_TEXTURE_CUBE_MAP_ARRAY) |
| { |
| s.outputType = "u" + outputBase + "2DArray"; |
| s.inputType = prefix + inputBase + "CubeArray"; |
| s.pointType = "ivec3"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.y, gl_WorkGroupID.z"; |
| } |
| else if (target == GL_TEXTURE_RECTANGLE) |
| { |
| s.inputType = prefix + inputBase + "2DRect"; |
| } |
| else if (target == GL_TEXTURE_2D_MULTISAMPLE) |
| { |
| s.inputType = prefix + inputBase + "2DMS"; |
| s.sampleDef = ", " + de::toString(sample); |
| } |
| else if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| s.outputType = "u" + outputBase + "2DArray"; |
| s.inputType = prefix + inputBase + "2DMSArray"; |
| s.pointType = "ivec3"; |
| s.pointDef = "gl_WorkGroupID.x, gl_WorkGroupID.y, gl_WorkGroupID.z"; |
| s.sampleDef = ", " + de::toString(sample); |
| } |
| |
| return s; |
| } |
| |
| /** Check if specific combination of target and format is allowed |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * |
| * @return Returns true if target/format combination is allowed, false otherwise. |
| */ |
| bool SparseTexture2CommitmentTestCase::caseAllowed(GLint target, GLint format) |
| { |
| // Multisample textures are filling with data and verifying using compute shader. |
| // As shaders do not support some texture formats it is necessary to exclude them. |
| if ((target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) && |
| (format == GL_RGB565 || format == GL_RGB10_A2UI || format == GL_RGB9_E5)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Allocating sparse texture memory using texStorage* function |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param levels Texture mipmaps level |
| * |
| * @return Returns true if no error occurred, otherwise throws an exception. |
| */ |
| bool SparseTexture2CommitmentTestCase::sparseAllocateTexture(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint levels) |
| { |
| mLog << "Sparse Allocate [levels: " << levels << "] - "; |
| |
| prepareTexture(gl, target, format, texture); |
| |
| GLint maxLevels; |
| gl.texParameteri(target, GL_TEXTURE_SPARSE_ARB, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri error occurred for GL_TEXTURE_SPARSE_ARB"); |
| gl.getTexParameteriv(target, GL_NUM_SPARSE_LEVELS_ARB, &maxLevels); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv"); |
| if (levels > maxLevels) |
| levels = maxLevels; |
| |
| //GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY can have only one level |
| if (target != GL_TEXTURE_RECTANGLE && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| mState.levels = levels; |
| } |
| else |
| mState.levels = 1; |
| |
| if (target != GL_TEXTURE_2D_MULTISAMPLE && target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| mState.samples = 1; |
| } |
| else |
| mState.samples = 2; |
| |
| Texture::Storage(gl, target, deMax32(mState.levels, mState.samples), format, mState.width, mState.height, |
| mState.depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage"); |
| |
| return true; |
| } |
| |
| /** Allocating texture memory using texStorage* function |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param levels Texture mipmaps level |
| * |
| * @return Returns true if no error occurred, otherwise throws an exception. |
| */ |
| bool SparseTexture2CommitmentTestCase::allocateTexture(const Functions& gl, GLint target, GLint format, GLuint& texture, |
| GLint levels) |
| { |
| mLog << "Allocate [levels: " << levels << "] - "; |
| |
| prepareTexture(gl, target, format, texture); |
| |
| // GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY can have only one level |
| if (target != GL_TEXTURE_RECTANGLE && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| mState.levels = levels; |
| } |
| else |
| mState.levels = 1; |
| |
| // GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY can use multiple samples |
| if (target != GL_TEXTURE_2D_MULTISAMPLE && target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| mState.samples = 1; |
| } |
| else |
| mState.samples = 2; |
| |
| Texture::Storage(gl, target, deMax32(mState.levels, mState.samples), format, mState.width, mState.height, |
| mState.depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage"); |
| |
| return true; |
| } |
| |
| /** Writing data to generated texture |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * |
| * @return Returns true if no error occurred, otherwise throws an exception. |
| */ |
| bool SparseTexture2CommitmentTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level) |
| { |
| mLog << "Fill Texture [level: " << level << "] - "; |
| |
| if (level > mState.levels - 1) |
| TCU_FAIL("Invalid level"); |
| |
| TransferFormat transferFormat = glu::getTransferFormat(mState.format); |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| if (width > 0 && height > 0 && depth >= mState.minDepth) |
| { |
| if (target == GL_TEXTURE_CUBE_MAP) |
| depth = depth * 6; |
| |
| GLint texSize = width * height * depth * mState.format.getPixelSize(); |
| |
| std::vector<GLubyte> vecData; |
| vecData.resize(texSize); |
| GLubyte* data = vecData.data(); |
| |
| deMemset(data, 255, texSize); |
| |
| if (target != GL_TEXTURE_2D_MULTISAMPLE && target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| Texture::SubImage(gl, target, level, 0, 0, 0, width, height, depth, transferFormat.format, |
| transferFormat.dataType, (GLvoid*)data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "SubImage"); |
| } |
| // For multisample texture use compute shader to store image data |
| else |
| { |
| for (GLint sample = 0; sample < mState.samples; ++sample) |
| { |
| std::string shader = st2_compute_textureFill; |
| |
| // Adjust shader source to texture format |
| TokenStrings s = createShaderTokens(target, format, sample); |
| |
| replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader); |
| replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader); |
| replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader); |
| replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader); |
| replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader); |
| replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader); |
| |
| ProgramSources sources; |
| sources << ComputeSource(shader); |
| |
| // Build and run shader |
| ShaderProgram program(m_context.getRenderContext(), sources); |
| if (program.isOk()) |
| { |
| gl.useProgram(program.getProgram()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); |
| gl.bindImageTexture(0 /* unit */, texture, level /* level */, GL_FALSE /* layered */, 0 /* layer */, |
| GL_WRITE_ONLY, format); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.uniform1i(1, 0 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.dispatchCompute(width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute"); |
| gl.memoryBarrier(GL_ALL_BARRIER_BITS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier"); |
| } |
| else |
| { |
| mLog << "Compute shader compilation failed (writing) for target: " << target |
| << ", format: " << format << ", sample: " << sample |
| << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog |
| << ", shaderSource: " << shader.c_str() << " - "; |
| } |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** Verify if data stored in texture is as expected |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * |
| * @return Returns true if data is as expected, false if not, throws an exception if error occurred. |
| */ |
| bool SparseTexture2CommitmentTestCase::verifyTextureData(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level) |
| { |
| mLog << "Verify Texture [level: " << level << "] - "; |
| |
| if (level > mState.levels - 1) |
| TCU_FAIL("Invalid level"); |
| |
| TransferFormat transferFormat = glu::getTransferFormat(mState.format); |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| //Committed region is limited to 1/2 of width |
| GLint widthCommitted = width / 2; |
| |
| if (widthCommitted == 0 || height == 0 || depth < mState.minDepth) |
| return true; |
| |
| bool result = true; |
| |
| if (target != GL_TEXTURE_CUBE_MAP && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| GLint texSize = width * height * depth * mState.format.getPixelSize(); |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| deMemset(exp_data, 255, texSize); |
| deMemset(out_data, 127, texSize); |
| |
| Texture::GetData(gl, level, target, transferFormat.format, transferFormat.dataType, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only committed region |
| for (GLint x = 0; x < widthCommitted; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| int pixelSize = mState.format.getPixelSize(); |
| GLubyte* dataRegion = exp_data + ((x + y * width) * pixelSize); |
| GLubyte* outDataRegion = out_data + ((x + y * width) * pixelSize); |
| if (deMemCmp(dataRegion, outDataRegion, pixelSize) != 0) |
| result = false; |
| } |
| } |
| else if (target == GL_TEXTURE_CUBE_MAP) |
| { |
| std::vector<GLint> subTargets; |
| |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); |
| |
| GLint texSize = width * height * mState.format.getPixelSize(); |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| deMemset(exp_data, 255, texSize); |
| |
| for (size_t i = 0; i < subTargets.size(); ++i) |
| { |
| GLint subTarget = subTargets[i]; |
| |
| mLog << "Verify Subtarget [subtarget: " << subTarget << "] - "; |
| |
| deMemset(out_data, 127, texSize); |
| |
| Texture::GetData(gl, level, subTarget, transferFormat.format, transferFormat.dataType, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only committed region |
| for (GLint x = 0; x < widthCommitted; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| int pixelSize = mState.format.getPixelSize(); |
| GLubyte* dataRegion = exp_data + ((x + y * width) * pixelSize); |
| GLubyte* outDataRegion = out_data + ((x + y * width) * pixelSize); |
| if (deMemCmp(dataRegion, outDataRegion, pixelSize) != 0) |
| result = false; |
| } |
| |
| if (!result) |
| break; |
| } |
| } |
| // For multisample texture use compute shader to verify image data |
| else if (target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| GLint texSize = width * height * depth; |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| deMemset(exp_data, 255, texSize); |
| |
| // Create verifying texture |
| GLint verifyTarget; |
| if (target == GL_TEXTURE_2D_MULTISAMPLE) |
| verifyTarget = GL_TEXTURE_2D; |
| else |
| verifyTarget = GL_TEXTURE_2D_ARRAY; |
| |
| GLuint verifyTexture; |
| Texture::Generate(gl, verifyTexture); |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage"); |
| |
| for (int sample = 0; sample < mState.samples; ++sample) |
| { |
| deMemset(out_data, 0, texSize); |
| |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, depth, GL_RED, GL_UNSIGNED_BYTE, |
| (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage"); |
| |
| std::string shader = st2_compute_textureVerify; |
| |
| // Adjust shader source to texture format |
| TokenStrings s = createShaderTokens(target, format, sample); |
| |
| replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), shader); |
| replaceToken("<FORMAT>", s.format.c_str(), shader); |
| replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader); |
| replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader); |
| replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader); |
| replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader); |
| replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader); |
| replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader); |
| replaceToken("<EPSILON>", s.epsilon.c_str(), shader); |
| |
| ProgramSources sources; |
| sources << ComputeSource(shader); |
| |
| // Build and run shader |
| ShaderProgram program(m_context.getRenderContext(), sources); |
| if (program.isOk()) |
| { |
| gl.useProgram(program.getProgram()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); |
| gl.bindImageTexture(0, //unit |
| verifyTexture, |
| 0, //level |
| GL_FALSE, //layered |
| 0, //layer |
| GL_WRITE_ONLY, GL_R8UI); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.bindImageTexture(1, //unit |
| texture, |
| level, //level |
| GL_FALSE, //layered |
| 0, //layer |
| GL_READ_ONLY, format); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.uniform1i(1, 0 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.uniform1i(2, 1 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.dispatchCompute(width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute"); |
| gl.memoryBarrier(GL_ALL_BARRIER_BITS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier"); |
| |
| Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only committed region |
| for (GLint x = 0; x < widthCommitted; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| GLubyte* dataRegion = exp_data + ((x + y * width) + z * width * height); |
| GLubyte* outDataRegion = out_data + ((x + y * width) + z * width * height); |
| if (dataRegion[0] != outDataRegion[0]) |
| result = false; |
| } |
| } |
| else |
| { |
| mLog << "Compute shader compilation failed (reading) for target: " << target << ", format: " << format |
| << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog |
| << ", shaderSource: " << shader.c_str() << " - "; |
| |
| result = false; |
| } |
| } |
| |
| Texture::Delete(gl, verifyTexture); |
| } |
| |
| return result; |
| } |
| |
| const GLfloat texCoord[] = { |
| 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, |
| }; |
| |
| const GLfloat vertices[] = { |
| -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, |
| }; |
| |
| const GLuint indices[] = { 0, 1, 2, 1, 2, 3 }; |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| UncommittedRegionsAccessTestCase::UncommittedRegionsAccessTestCase(deqp::Context& context) |
| : SparseTexture2CommitmentTestCase(context, "UncommittedRegionsAccess", |
| "Verifies if access to uncommitted regions of sparse texture works as expected") |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Stub init method */ |
| void UncommittedRegionsAccessTestCase::init() |
| { |
| SparseTextureCommitmentTestCase::init(); |
| |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult UncommittedRegionsAccessTestCase::iterate() |
| { |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2")) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| return STOP; |
| } |
| |
| const Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool result = true; |
| |
| GLuint texture; |
| |
| for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end(); |
| ++iter) |
| { |
| const GLint& target = *iter; |
| |
| for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin(); |
| formIter != mSupportedInternalFormats.end(); ++formIter) |
| { |
| const GLint& format = *formIter; |
| |
| if (!caseAllowed(target, format)) |
| continue; |
| |
| mLog.str(""); |
| mLog << "Testing uncommitted regions access for target: " << target << ", format: " << format << " - "; |
| |
| sparseAllocateTexture(gl, target, format, texture, 3); |
| for (int l = 0; l < mState.levels; ++l) |
| { |
| if (commitTexturePage(gl, target, format, texture, l)) |
| { |
| writeDataToTexture(gl, target, format, texture, l); |
| result = result && UncommittedReads(gl, target, format, texture, l); |
| result = result && UncommittedAtomicOperations(gl, target, format, texture, l); |
| } |
| |
| if (!result) |
| break; |
| } |
| |
| Texture::Delete(gl, texture); |
| |
| if (!result) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage; |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| return STOP; |
| } |
| } |
| } |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| return STOP; |
| } |
| |
| /** Check if reads from uncommitted regions are allowed |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * |
| * @return Returns true if allowed, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::readsAllowed(GLint target, GLint format, bool shaderOnly) |
| { |
| DE_UNREF(target); |
| |
| if (shaderOnly && (format == GL_RGB565 || format == GL_RGB10_A2UI || format == GL_RGB9_E5)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Check if atomic operations on uncommitted regions are allowed |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * |
| * @return Returns true if allowed, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::atomicAllowed(GLint target, GLint format) |
| { |
| DE_UNREF(target); |
| |
| if (format == GL_R32I || format == GL_R32UI) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** Check if depth and stencil test on uncommitted regions are allowed |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * |
| * @return Returns true if allowed, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::depthStencilAllowed(GLint target, GLint format) |
| { |
| if (target == GL_TEXTURE_2D && format == GL_RGBA8) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** Verify reads from uncommitted texture regions works as expected |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * |
| * @return Returns true if data is as expected, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::UncommittedReads(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level) |
| { |
| bool result = true; |
| |
| // Verify using API glGetTexImage* |
| if (readsAllowed(target, format, false)) |
| { |
| mLog << "API Reads - "; |
| result = result && verifyTextureDataExtended(gl, target, format, texture, level, false); |
| } |
| |
| // Verify using shader imageLoad function |
| if (result && readsAllowed(target, format, true)) |
| { |
| mLog << "Shader Reads - "; |
| result = result && verifyTextureDataExtended(gl, target, format, texture, level, true); |
| } |
| |
| // Verify mipmap generating |
| if (result && level == 0 && target != GL_TEXTURE_RECTANGLE && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| mLog << "Mipmap Generate - "; |
| Texture::Bind(gl, texture, target); |
| gl.generateMipmap(target); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap"); |
| |
| for (int l = 1; l < mState.levels; ++l) |
| result = result && verifyTextureDataExtended(gl, target, format, texture, level, false); |
| } |
| |
| return result; |
| } |
| |
| /** Verify atomic operations on uncommitted texture pixels works as expected |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * |
| * @return Returns true if data is as expected, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::UncommittedAtomicOperations(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level) |
| { |
| bool result = true; |
| |
| if (atomicAllowed(target, format)) |
| { |
| mLog << "Atomic Operations - "; |
| result = result && verifyAtomicOperations(gl, target, format, texture, level); |
| } |
| |
| return result; |
| } |
| |
| /** Verify depth and stencil tests on uncommitted texture pixels works as expected |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * |
| * @return Returns true if data is as expected, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::UncommittedDepthStencil(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level) |
| { |
| if (!depthStencilAllowed(target, format)) |
| return true; |
| |
| mLog << "Depth Stencil - "; |
| |
| bool result = true; |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| //Committed region is limited to 1/2 of width |
| GLuint widthCommitted = width / 2; |
| |
| if (widthCommitted == 0 || height == 0 || depth < mState.minDepth) |
| return true; |
| |
| //Prepare shaders |
| std::string vertexSource = st2_vertex_drawBuffer; |
| std::string fragmentSource = st2_fragment_drawBuffer; |
| |
| ShaderProgram program(gl, glu::makeVtxFragSources(vertexSource, fragmentSource)); |
| if (!program.isOk()) |
| { |
| mLog << "Shader compilation failed (depth_stencil) for target: " << target << ", format: " << format |
| << ", vertex_infoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog |
| << ", fragment_infoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog |
| << ", vertexSource: " << vertexSource.c_str() << "\n" |
| << ", fragmentSource: " << fragmentSource.c_str() << " - "; |
| |
| return false; |
| } |
| |
| prepareDepthStencilFramebuffer(gl, width, height); |
| |
| gl.useProgram(program.getProgram()); |
| |
| gl.activeTexture(GL_TEXTURE0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture"); |
| Texture::Bind(gl, texture, target); |
| gl.uniform1i(1, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| |
| // Stencil test |
| result = result && verifyStencilTest(gl, program, width, height, widthCommitted); |
| |
| // Depth test |
| result = result && verifyDepthTest(gl, program, width, height, widthCommitted); |
| |
| // Depth bounds test |
| if (m_context.getContextInfo().isExtensionSupported("GL_EXT_depth_bounds_test")) |
| result = result && verifyDepthBoundsTest(gl, program, width, height, widthCommitted); |
| |
| // Resources cleaning |
| cleanupDepthStencilFramebuffer(gl); |
| |
| return result; |
| } |
| |
| /** Prepare gl depth and stencil test resources |
| * |
| * @param gl GL API functions |
| * @param width Framebuffer width |
| * @param height Framebuffer height |
| */ |
| void UncommittedRegionsAccessTestCase::prepareDepthStencilFramebuffer(const Functions& gl, GLint width, GLint height) |
| { |
| gl.genRenderbuffers(1, &mRenderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers"); |
| gl.bindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer"); |
| if (mState.samples == 1) |
| { |
| gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage"); |
| } |
| else |
| { |
| gl.renderbufferStorageMultisample(GL_RENDERBUFFER, mState.samples, GL_DEPTH_STENCIL, width, height); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorageMultisample"); |
| } |
| |
| gl.genFramebuffers(1, &mFramebuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers"); |
| gl.bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer"); |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer"); |
| gl.viewport(0, 0, width, height); |
| } |
| |
| /** Cleanup gl depth and stencil test resources |
| * |
| * @param gl GL API functions |
| */ |
| void UncommittedRegionsAccessTestCase::cleanupDepthStencilFramebuffer(const Functions& gl) |
| { |
| gl.deleteFramebuffers(1, &mFramebuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers"); |
| gl.deleteRenderbuffers(1, &mRenderbuffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteRenderbuffers"); |
| |
| gl.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer"); |
| } |
| |
| /** Verify if data stored in texture in uncommitted regions is as expected |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * @param shaderOnly Shader texture filling flag, default false |
| * |
| * @return Returns true if data is as expected, false if not, throws an exception if error occurred. |
| */ |
| bool UncommittedRegionsAccessTestCase::verifyTextureDataExtended(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level, bool shaderOnly) |
| { |
| mLog << "Verify Texture [level: " << level << "] - "; |
| |
| if (level > mState.levels - 1) |
| TCU_FAIL("Invalid level"); |
| |
| TransferFormat transferFormat = glu::getTransferFormat(mState.format); |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| //Committed region is limited to 1/2 of width |
| GLint widthCommitted = width / 2; |
| |
| if (widthCommitted == 0 || height == 0 || depth < mState.minDepth) |
| return true; |
| |
| bool result = true; |
| |
| // Verify texture using API glGetTexImage* (Skip multisample textures as it can not be verified using API) |
| if (!shaderOnly && target != GL_TEXTURE_CUBE_MAP && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| GLint texSize = width * height * depth * mState.format.getPixelSize(); |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| // Expected value in this case is 0 because atomic operations result on uncommitted regions are zeros |
| deMemset(exp_data, 0, texSize); |
| deMemset(out_data, 255, texSize); |
| |
| Texture::GetData(gl, level, target, transferFormat.format, transferFormat.dataType, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only uncommitted region |
| for (GLint x = widthCommitted; x < width; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| int pixelSize = mState.format.getPixelSize(); |
| GLubyte* dataRegion = exp_data + ((x + y * width) * pixelSize); |
| GLubyte* outDataRegion = out_data + ((x + y * width) * pixelSize); |
| if (deMemCmp(dataRegion, outDataRegion, pixelSize) != 0) |
| result = false; |
| } |
| } |
| // Verify texture using API glGetTexImage* (Only cube map as it has to be verified for subtargets) |
| else if (!shaderOnly && target == GL_TEXTURE_CUBE_MAP) |
| { |
| std::vector<GLint> subTargets; |
| |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); |
| subTargets.push_back(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); |
| |
| GLint texSize = width * height * mState.format.getPixelSize(); |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| deMemset(exp_data, 0, texSize); |
| |
| for (size_t i = 0; i < subTargets.size(); ++i) |
| { |
| GLint subTarget = subTargets[i]; |
| |
| mLog << "Verify Subtarget [subtarget: " << subTarget << "] - "; |
| |
| deMemset(out_data, 255, texSize); |
| |
| Texture::GetData(gl, level, subTarget, transferFormat.format, transferFormat.dataType, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only uncommitted region |
| for (GLint x = widthCommitted; x < width; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| int pixelSize = mState.format.getPixelSize(); |
| GLubyte* dataRegion = exp_data + ((x + y * width) * pixelSize); |
| GLubyte* outDataRegion = out_data + ((x + y * width) * pixelSize); |
| if (deMemCmp(dataRegion, outDataRegion, pixelSize) != 0) |
| result = false; |
| } |
| |
| if (!result) |
| break; |
| } |
| } |
| // Verify texture using shader imageLoad function |
| else if (shaderOnly) |
| { |
| // Create verifying texture |
| GLint verifyTarget; |
| if (target == GL_TEXTURE_2D_MULTISAMPLE) |
| verifyTarget = GL_TEXTURE_2D; |
| else |
| verifyTarget = GL_TEXTURE_2D_ARRAY; |
| |
| if (target == GL_TEXTURE_CUBE_MAP) |
| depth = depth * 6; |
| |
| GLint texSize = width * height * depth; |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| // Expected value in this case is 255 because shader fills output texture with 255 if in texture is filled with zeros |
| deMemset(exp_data, 255, texSize); |
| |
| GLuint verifyTexture; |
| Texture::Generate(gl, verifyTexture); |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage"); |
| |
| for (GLint sample = 0; sample < mState.samples; ++sample) |
| { |
| deMemset(out_data, 0, texSize); |
| |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, depth, GL_RED, GL_UNSIGNED_BYTE, |
| (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage"); |
| |
| std::string shader = st2_compute_textureVerify; |
| |
| // Adjust shader source to texture format |
| TokenStrings s = createShaderTokens(target, format, sample); |
| |
| replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), shader); |
| replaceToken("<FORMAT>", s.format.c_str(), shader); |
| replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader); |
| replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader); |
| replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader); |
| replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader); |
| replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader); |
| replaceToken("<RESULT_EXPECTED>", s.resultDefault.c_str(), shader); |
| replaceToken("<EPSILON>", s.epsilon.c_str(), shader); |
| |
| ProgramSources sources; |
| sources << ComputeSource(shader); |
| |
| // Build and run shader |
| ShaderProgram program(m_context.getRenderContext(), sources); |
| if (program.isOk()) |
| { |
| gl.useProgram(program.getProgram()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); |
| gl.bindImageTexture(0, //unit |
| verifyTexture, |
| 0, //level |
| GL_FALSE, //layered |
| 0, //layer |
| GL_WRITE_ONLY, GL_R8UI); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.bindImageTexture(1, //unit |
| texture, |
| level, //level |
| GL_FALSE, //layered |
| 0, //layer |
| GL_READ_ONLY, format); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.uniform1i(1, 0 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.uniform1i(2, 1 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.dispatchCompute(width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute"); |
| gl.memoryBarrier(GL_ALL_BARRIER_BITS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier"); |
| |
| Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only committed region |
| for (GLint x = widthCommitted; x < width; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| GLubyte* dataRegion = exp_data + ((x + y * width) + z * width * height); |
| GLubyte* outDataRegion = out_data + ((x + y * width) + z * width * height); |
| if (dataRegion[0] != outDataRegion[0]) |
| result = false; |
| } |
| } |
| else |
| { |
| mLog << "Compute shader compilation failed (reading) for target: " << target << ", format: " << format |
| << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog |
| << ", shaderSource: " << shader.c_str() << " - "; |
| |
| result = false; |
| } |
| } |
| |
| Texture::Delete(gl, verifyTexture); |
| } |
| |
| return result; |
| } |
| |
| /** Verify if atomic operations on uncommitted regions returns zeros and has no effect on texture |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * |
| * @return Returns true if data is as expected, false if not, throws an exception if error occurred. |
| */ |
| bool UncommittedRegionsAccessTestCase::verifyAtomicOperations(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level) |
| { |
| mLog << "Verify Atomic Operations [level: " << level << "] - "; |
| |
| if (level > mState.levels - 1) |
| TCU_FAIL("Invalid level"); |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| //Committed region is limited to 1/2 of width |
| GLint widthCommitted = width / 2; |
| |
| if (widthCommitted == 0 || height == 0 || depth < mState.minDepth) |
| return true; |
| |
| bool result = true; |
| |
| // Create verifying texture |
| GLint verifyTarget; |
| if (target == GL_TEXTURE_2D_MULTISAMPLE) |
| verifyTarget = GL_TEXTURE_2D; |
| else |
| verifyTarget = GL_TEXTURE_2D_ARRAY; |
| |
| GLint texSize = width * height * depth; |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| // Expected value in this case is 0 because atomic operations result on uncommitted regions are zeros |
| deMemset(exp_data, 0, texSize); |
| |
| GLuint verifyTexture; |
| Texture::Generate(gl, verifyTexture); |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage"); |
| |
| for (GLint sample = 0; sample < mState.samples; ++sample) |
| { |
| deMemset(out_data, 255, texSize); |
| |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, depth, GL_RED, GL_UNSIGNED_BYTE, |
| (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage"); |
| |
| std::string shader = st2_compute_atomicVerify; |
| |
| // Adjust shader source to texture format |
| TokenStrings s = createShaderTokens(target, format, sample); |
| std::string dataType = (s.returnType == "ivec4" ? "int" : "uint"); |
| |
| replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), shader); |
| replaceToken("<FORMAT>", s.format.c_str(), shader); |
| replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader); |
| replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader); |
| replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader); |
| replaceToken("<DATA_TYPE>", dataType.c_str(), shader); |
| replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader); |
| replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader); |
| |
| ProgramSources sources; |
| sources << ComputeSource(shader); |
| |
| // Build and run shader |
| ShaderProgram program(m_context.getRenderContext(), sources); |
| if (program.isOk()) |
| { |
| gl.useProgram(program.getProgram()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); |
| gl.bindImageTexture(0, //unit |
| verifyTexture, |
| 0, //level |
| GL_FALSE, //layered |
| 0, //layer |
| GL_WRITE_ONLY, GL_R8UI); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.bindImageTexture(1, //unit |
| texture, |
| level, //level |
| GL_FALSE, //layered |
| 0, //layer |
| GL_READ_ONLY, format); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.uniform1i(1, 0 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.uniform1i(2, 1 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.uniform1i(3, widthCommitted /* committed width */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.dispatchCompute(width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute"); |
| gl.memoryBarrier(GL_ALL_BARRIER_BITS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier"); |
| |
| Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData"); |
| |
| //Verify only committed region |
| for (GLint x = 0; x < width; ++x) |
| for (GLint y = 0; y < height; ++y) |
| for (GLint z = 0; z < depth; ++z) |
| { |
| GLubyte* dataRegion = exp_data + ((x + y * width) + z * width * height); |
| GLubyte* outDataRegion = out_data + ((x + y * width) + z * width * height); |
| if (dataRegion[0] != outDataRegion[0]) |
| { |
| printf("%d:%d ", dataRegion[0], outDataRegion[0]); |
| result = false; |
| } |
| } |
| } |
| else |
| { |
| mLog << "Compute shader compilation failed (atomic) for target: " << target << ", format: " << format |
| << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog |
| << ", shaderSource: " << shader.c_str() << " - "; |
| |
| result = false; |
| } |
| } |
| |
| Texture::Delete(gl, verifyTexture); |
| |
| return result; |
| } |
| |
| /** Verify if stencil test on uncommitted texture region works as expected texture |
| * |
| * @param gl GL API functions |
| * @param program Shader program |
| * @param width Texture width |
| * @param height Texture height |
| * @param widthCommitted Committed region width |
| * |
| * @return Returns true if stencil data is as expected, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::verifyStencilTest(const Functions& gl, ShaderProgram& program, GLint width, |
| GLint height, GLint widthCommitted) |
| { |
| glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), |
| glu::va::Float("inTexCoord", 2, 4, 0, texCoord) }; |
| |
| mLog << "Perform Stencil Test - "; |
| |
| gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| gl.enable(GL_STENCIL_TEST); |
| gl.stencilFunc(GL_GREATER, 1, 0xFF); |
| gl.stencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); |
| |
| glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, |
| glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices)); |
| |
| std::vector<GLubyte> dataStencil; |
| dataStencil.resize(width * height); |
| GLubyte* dataStencilPtr = dataStencil.data(); |
| |
| gl.readPixels(0, 0, width, height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, (GLvoid*)dataStencilPtr); |
| for (int x = widthCommitted; x < width; ++x) |
| for (int y = 0; y < height; ++y) |
| { |
| if (dataStencilPtr[x + y * width] != 0x00) |
| { |
| gl.disable(GL_STENCIL_TEST); |
| return false; |
| } |
| } |
| |
| gl.disable(GL_STENCIL_TEST); |
| return true; |
| } |
| |
| /** Verify if depth test on uncommitted texture region works as expected texture |
| * |
| * @param gl GL API functions |
| * @param program Shader program |
| * @param width Texture width |
| * @param height Texture height |
| * @param widthCommitted Committed region width |
| * |
| * @return Returns true if depth data is as expected, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::verifyDepthTest(const Functions& gl, ShaderProgram& program, GLint width, |
| GLint height, GLint widthCommitted) |
| { |
| glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), |
| glu::va::Float("inTexCoord", 2, 4, 0, texCoord) }; |
| |
| mLog << "Perform Depth Test - "; |
| |
| gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| gl.enable(GL_DEPTH_TEST); |
| gl.depthFunc(GL_LESS); |
| |
| glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, |
| glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices)); |
| |
| std::vector<GLuint> dataDepth; |
| dataDepth.resize(width * height); |
| GLuint* dataDepthPtr = dataDepth.data(); |
| |
| gl.readPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, (GLvoid*)dataDepthPtr); |
| for (int x = widthCommitted; x < width; ++x) |
| for (int y = 0; y < height; ++y) |
| { |
| if (dataDepthPtr[x + y * width] != 0xFFFFFFFF) |
| { |
| gl.disable(GL_DEPTH_TEST); |
| return false; |
| } |
| } |
| |
| gl.disable(GL_DEPTH_TEST); |
| return true; |
| } |
| |
| /** Verify if depth bounds test on uncommitted texture region works as expected texture |
| * |
| * @param gl GL API functions |
| * @param program Shader program |
| * @param width Texture width |
| * @param height Texture height |
| * @param widthCommitted Committed region width |
| * |
| * @return Returns true if depth data is as expected, false otherwise. |
| */ |
| bool UncommittedRegionsAccessTestCase::verifyDepthBoundsTest(const Functions& gl, ShaderProgram& program, GLint width, |
| GLint height, GLint widthCommitted) |
| { |
| glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), |
| glu::va::Float("inTexCoord", 2, 4, 0, texCoord) }; |
| |
| mLog << "Perform Depth Bounds Test - "; |
| |
| gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| gl.enable(GL_DEPTH_BOUNDS_TEST_EXT); |
| gl.depthFunc(GL_LESS); |
| |
| glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays, |
| glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices)); |
| |
| std::vector<GLuint> dataDepth; |
| dataDepth.resize(width * height); |
| GLuint* dataDepthPtr = dataDepth.data(); |
| |
| gl.readPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, (GLvoid*)dataDepthPtr); |
| for (int x = widthCommitted; x < width; ++x) |
| for (int y = 0; y < height; ++y) |
| { |
| if (dataDepthPtr[x + y * width] != 0xFFFFFFFF) |
| { |
| gl.disable(GL_DEPTH_BOUNDS_TEST_EXT); |
| return false; |
| } |
| } |
| |
| gl.disable(GL_DEPTH_BOUNDS_TEST_EXT); |
| return true; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| SparseTexture2LookupTestCase::SparseTexture2LookupTestCase(deqp::Context& context) |
| : SparseTexture2CommitmentTestCase(context, "SparseTexture2Lookup", |
| "Verifies if sparse texture lookup functions for GLSL works as expected") |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| */ |
| SparseTexture2LookupTestCase::SparseTexture2LookupTestCase(deqp::Context& context, const char* name, |
| const char* description) |
| : SparseTexture2CommitmentTestCase(context, name, description) |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Initializes the test group contents. */ |
| void SparseTexture2LookupTestCase::init() |
| { |
| SparseTextureCommitmentTestCase::init(); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE); |
| mSupportedTargets.push_back(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| |
| mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16); |
| |
| FunctionToken f; |
| f = FunctionToken("sparseTextureARB", "<CUBE_REFZ_DEF>"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureLodARB", ", <LOD>"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureOffsetARB", ", <OFFSET_TYPE><OFFSET_DIM>(0)"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTexelFetchARB", "<LOD_DEF>"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| f.allowedTargets.insert(GL_TEXTURE_2D_MULTISAMPLE); |
| f.allowedTargets.insert(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTexelFetchOffsetARB", "<LOD_DEF>, <OFFSET_TYPE><OFFSET_DIM>(0)"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureLodOffsetARB", ", <LOD>, <OFFSET_TYPE><OFFSET_DIM>(0)"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureGradARB", ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0)"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureGradOffsetARB", |
| ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0)"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureGatherARB", "<REFZ_DEF>"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureGatherOffsetARB", "<REFZ_DEF>, <OFFSET_TYPE><OFFSET_DIM>(0)"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseTextureGatherOffsetsARB", "<REFZ_DEF>, offsetsArray"); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| mFunctions.push_back(f); |
| |
| f = FunctionToken("sparseImageLoadARB", ""); |
| f.allowedTargets.insert(GL_TEXTURE_2D); |
| f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP); |
| f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY); |
| f.allowedTargets.insert(GL_TEXTURE_3D); |
| f.allowedTargets.insert(GL_TEXTURE_RECTANGLE); |
| f.allowedTargets.insert(GL_TEXTURE_2D_MULTISAMPLE); |
| f.allowedTargets.insert(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); |
| //mFunctions.push_back(f); |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult SparseTexture2LookupTestCase::iterate() |
| { |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2")) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| return STOP; |
| } |
| |
| const Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| bool result = true; |
| |
| GLuint texture; |
| |
| for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end(); |
| ++iter) |
| { |
| const GLint& target = *iter; |
| |
| for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin(); |
| formIter != mSupportedInternalFormats.end(); ++formIter) |
| { |
| const GLint& format = *formIter; |
| |
| if (!caseAllowed(target, format)) |
| continue; |
| |
| for (std::vector<FunctionToken>::const_iterator tokIter = mFunctions.begin(); tokIter != mFunctions.end(); |
| ++tokIter) |
| { |
| // Check if target is allowed for current lookup function |
| FunctionToken funcToken = *tokIter; |
| if (!funcAllowed(target, format, funcToken)) |
| continue; |
| |
| mLog.str(""); |
| mLog << "Testing sparse texture lookup functions for target: " << target << ", format: " << format |
| << " - "; |
| |
| sparseAllocateTexture(gl, target, format, texture, 3); |
| if (format == GL_DEPTH_COMPONENT16) |
| setupDepthMode(gl, target, texture); |
| |
| for (int l = 0; l < mState.levels; ++l) |
| { |
| if (commitTexturePage(gl, target, format, texture, l)) |
| { |
| writeDataToTexture(gl, target, format, texture, l); |
| result = result && verifyLookupTextureData(gl, target, format, texture, l, funcToken); |
| } |
| |
| if (!result) |
| break; |
| } |
| |
| Texture::Delete(gl, texture); |
| |
| if (!result) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage; |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| return STOP; |
| } |
| } |
| } |
| } |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| return STOP; |
| } |
| |
| /** Create set of token strings fit to lookup functions verifying shader |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param level Texture mipmap level |
| * @param sample Texture sample number |
| * @param funcToken Texture lookup function structure |
| * |
| * @return Returns extended token strings structure. |
| */ |
| SparseTexture2LookupTestCase::TokenStringsExt SparseTexture2LookupTestCase::createLookupShaderTokens( |
| GLint target, GLint format, GLint level, GLint sample, FunctionToken& funcToken) |
| { |
| std::string funcName = funcToken.name; |
| |
| TokenStringsExt s; |
| |
| std::string inputType; |
| std::string samplerSufix; |
| |
| if (funcName == "sparseImageLoadARB") |
| inputType = "image"; |
| else |
| inputType = "sampler"; |
| |
| // Copy data from TokenStrings to TokenStringsExt |
| TokenStrings ss = createShaderTokens(target, format, sample, "image", inputType); |
| s.epsilon = ss.epsilon; |
| s.format = ss.format; |
| s.inputType = ss.inputType; |
| s.outputType = ss.outputType; |
| s.pointDef = ss.pointDef; |
| s.pointType = ss.pointType; |
| s.resultDefault = ss.resultDefault; |
| s.resultExpected = ss.resultExpected; |
| s.returnType = ss.returnType; |
| s.sampleDef = ss.sampleDef; |
| |
| // Set format definition for image input types |
| if (inputType == "image") |
| s.formatDef = ", " + s.format; |
| |
| // Set tokens for depth texture format |
| if (format == GL_DEPTH_COMPONENT16) |
| { |
| s.refZDef = ", 0.5"; |
| |
| if (inputType == "sampler" && target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| s.inputType = s.inputType + "Shadow"; |
| } |
| } |
| |
| // Set coord type, coord definition and offset vector dimensions |
| s.coordType = "vec2"; |
| s.offsetType = "ivec"; |
| s.nOffsetType = "vec"; |
| s.offsetDim = "2"; |
| if (target == GL_TEXTURE_1D) |
| { |
| s.coordType = "float"; |
| s.offsetType = "int"; |
| s.nOffsetType = "float"; |
| s.offsetDim = ""; |
| } |
| else if (target == GL_TEXTURE_1D_ARRAY) |
| { |
| s.coordType = "vec2"; |
| s.offsetType = "int"; |
| s.nOffsetType = "float"; |
| s.offsetDim = ""; |
| } |
| else if (target == GL_TEXTURE_2D_ARRAY) |
| { |
| s.coordType = "vec3"; |
| } |
| else if (target == GL_TEXTURE_3D) |
| { |
| s.coordType = "vec3"; |
| s.offsetDim = "3"; |
| } |
| else if (target == GL_TEXTURE_CUBE_MAP) |
| { |
| s.coordType = "vec3"; |
| s.offsetDim = "3"; |
| } |
| else if (target == GL_TEXTURE_CUBE_MAP_ARRAY) |
| { |
| s.coordType = "vec4"; |
| s.coordDef = "gl_WorkGroupID.x, gl_WorkGroupID.y, gl_WorkGroupID.z % 6, floor(gl_WorkGroupID.z / 6)"; |
| s.offsetDim = "3"; |
| } |
| else if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| s.coordType = "vec3"; |
| } |
| |
| if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) && |
| funcName.find("Fetch", 0) == std::string::npos) |
| { |
| s.cubeMapCoordDef = " int face = point.z % 6;\n" |
| " if (face == 0) coord.xyz = vec3(1, coord.y * 2 - 1, -coord.x * 2 + 1);\n" |
| " if (face == 1) coord.xyz = vec3(-1, coord.y * 2 - 1, coord.x * 2 - 1);\n" |
| " if (face == 2) coord.xyz = vec3(coord.x * 2 - 1, 1, coord.y * 2 - 1);\n" |
| " if (face == 3) coord.xyz = vec3(coord.x * 2 - 1, -1, -coord.y * 2 + 1);\n" |
| " if (face == 4) coord.xyz = vec3(coord.x * 2 - 1, coord.y * 2 - 1, 1);\n" |
| " if (face == 5) coord.xyz = vec3(-coord.x * 2 + 1, coord.y * 2 - 1, -1);\n"; |
| } |
| |
| if (s.coordDef.empty()) |
| s.coordDef = s.pointDef; |
| |
| // Set expected result vector, component definition and offset array definition for gather functions |
| if (funcName.find("Gather", 0) != std::string::npos) |
| { |
| if (funcName.find("GatherOffsets", 0) != std::string::npos) |
| { |
| s.offsetArrayDef = " <OFFSET_TYPE><OFFSET_DIM> offsetsArray[4];\n" |
| " offsetsArray[0] = <OFFSET_TYPE><OFFSET_DIM>(0);\n" |
| " offsetsArray[1] = <OFFSET_TYPE><OFFSET_DIM>(0);\n" |
| " offsetsArray[2] = <OFFSET_TYPE><OFFSET_DIM>(0);\n" |
| " offsetsArray[3] = <OFFSET_TYPE><OFFSET_DIM>(0);\n"; |
| } |
| |
| if (format != GL_DEPTH_COMPONENT16) |
| s.componentDef = ", 0"; |
| s.resultExpected = "(1, 1, 1, 1)"; |
| } |
| // Extend coord type dimension and coord vector definition if shadow sampler and non-cube map array target selected |
| // Set component definition to red component |
| else if (format == GL_DEPTH_COMPONENT16) |
| { |
| if (target != GL_TEXTURE_CUBE_MAP_ARRAY) |
| { |
| if (s.coordType == "float") |
| s.coordType = "vec3"; |
| else if (s.coordType == "vec2") |
| s.coordType = "vec3"; |
| else if (s.coordType == "vec3") |
| s.coordType = "vec4"; |
| s.coordDef += s.refZDef; |
| } |
| else |
| s.cubeMapArrayRefZDef = s.refZDef; |
| |
| s.componentDef = ".r"; |
| } |
| |
| // Set level of details definition |
| if (target != GL_TEXTURE_RECTANGLE && target != GL_TEXTURE_2D_MULTISAMPLE && |
| target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) |
| { |
| s.lod = de::toString(level); |
| s.lodDef = ", " + de::toString(level); |
| } |
| |
| // Set proper coord vector |
| if (target == GL_TEXTURE_RECTANGLE || funcName.find("Fetch") != std::string::npos || |
| funcName.find("ImageLoad") != std::string::npos) |
| { |
| s.pointCoord = "icoord"; |
| } |
| else |
| s.pointCoord = "coord"; |
| |
| // Set size vector definition |
| if (format != GL_DEPTH_COMPONENT16 || funcName.find("Gather", 0) != std::string::npos) |
| { |
| if (s.coordType == "float") |
| s.sizeDef = "<TEX_WIDTH>"; |
| else if (s.coordType == "vec2" && target == GL_TEXTURE_1D_ARRAY) |
| s.sizeDef = "<TEX_WIDTH>, <TEX_DEPTH>"; |
| else if (s.coordType == "vec2") |
| s.sizeDef = "<TEX_WIDTH>, <TEX_HEIGHT>"; |
| else if (s.coordType == "vec3") |
| s.sizeDef = "<TEX_WIDTH>, <TEX_HEIGHT>, <TEX_DEPTH>"; |
| else if (s.coordType == "vec4") |
| s.sizeDef = "<TEX_WIDTH>, <TEX_HEIGHT>, 6, floor(<TEX_DEPTH> / 6)"; |
| } |
| // Set size vector for shadow samplers and non-gether functions selected |
| else |
| { |
| if (s.coordType == "vec3" && target == GL_TEXTURE_1D) |
| s.sizeDef = "<TEX_WIDTH>, 1 , 1"; |
| else if (s.coordType == "vec3" && target == GL_TEXTURE_1D_ARRAY) |
| s.sizeDef = "<TEX_WIDTH>, <TEX_DEPTH>, 1"; |
| else if (s.coordType == "vec3") |
| s.sizeDef = "<TEX_WIDTH>, <TEX_HEIGHT>, 1"; |
| else if (s.coordType == "vec4") |
| s.sizeDef = "<TEX_WIDTH>, <TEX_HEIGHT>, <TEX_DEPTH>, 1"; |
| } |
| |
| if (s.coordType != "float") |
| s.iCoordType = "i" + s.coordType; |
| else |
| s.iCoordType = "int"; |
| |
| return s; |
| } |
| |
| /** Check if specific combination of target and format is |
| |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * |
| * @return Returns true if target/format combination is allowed, false otherwise. |
| */ |
| bool SparseTexture2LookupTestCase::caseAllowed(GLint target, GLint format) |
| { |
| DE_UNREF(target); |
| |
| // As shaders do not support some texture formats it is necessary to exclude them. |
| if (format == GL_RGB565 || format == GL_RGB10_A2UI || format == GL_RGB9_E5) |
| { |
| return false; |
| } |
| |
| if ((target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY || target == GL_TEXTURE_3D) && |
| (format == GL_DEPTH_COMPONENT16)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** Check if specific lookup function is allowed for specific target and format |
| * |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param funcToken Texture lookup function structure |
| * |
| * @return Returns true if target/format combination is allowed, false otherwise. |
| */ |
| bool SparseTexture2LookupTestCase::funcAllowed(GLint target, GLint format, FunctionToken& funcToken) |
| { |
| if (funcToken.allowedTargets.find(target) == funcToken.allowedTargets.end()) |
| return false; |
| |
| if (format == GL_DEPTH_COMPONENT16) |
| { |
| if (funcToken.name == "sparseTextureLodARB" || funcToken.name == "sparseTextureLodOffsetARB") |
| { |
| if (target != GL_TEXTURE_2D) |
| return false; |
| } |
| else if (funcToken.name == "sparseTextureOffsetARB" || funcToken.name == "sparseTextureGradOffsetARB" || |
| funcToken.name == "sparseTextureGatherOffsetARB" || funcToken.name == "sparseTextureGatherOffsetsARB") |
| { |
| if (target != GL_TEXTURE_2D && target != GL_TEXTURE_2D_ARRAY && target != GL_TEXTURE_RECTANGLE) |
| { |
| return false; |
| } |
| } |
| else if (funcToken.name == "sparseTexelFetchARB" || funcToken.name == "sparseTexelFetchOffsetARB") |
| { |
| return false; |
| } |
| else if (funcToken.name == "sparseTextureGradARB") |
| { |
| if (target == GL_TEXTURE_CUBE_MAP_ARRAY) |
| return false; |
| } |
| else if (funcToken.name == "sparseImageLoadARB") |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** Writing data to generated texture using compute shader |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * |
| * @return Returns true if no error occurred, otherwise throws an exception. |
| */ |
| bool SparseTexture2LookupTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format, GLuint& texture, |
| GLint level) |
| { |
| mLog << "Fill Texture with shader [level: " << level << "] - "; |
| |
| if (level > mState.levels - 1) |
| TCU_FAIL("Invalid level"); |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| if (width > 0 && height > 0 && depth >= mState.minDepth) |
| { |
| if (target == GL_TEXTURE_CUBE_MAP) |
| depth = depth * 6; |
| |
| GLint texSize = width * height * depth * mState.format.getPixelSize(); |
| |
| std::vector<GLubyte> vecData; |
| vecData.resize(texSize); |
| GLubyte* data = vecData.data(); |
| |
| deMemset(data, 255, texSize); |
| |
| for (GLint sample = 0; sample < mState.samples; ++sample) |
| { |
| std::string shader = st2_compute_textureFill; |
| |
| // Adjust shader source to texture format |
| TokenStrings s = createShaderTokens(target, format, sample); |
| |
| replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader); |
| replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader); |
| replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader); |
| replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader); |
| replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader); |
| replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader); |
| |
| ProgramSources sources; |
| sources << ComputeSource(shader); |
| |
| GLint convFormat = format; |
| if (format == GL_DEPTH_COMPONENT16) |
| convFormat = GL_R16; |
| |
| // Build and run shader |
| ShaderProgram program(m_context.getRenderContext(), sources); |
| if (program.isOk()) |
| { |
| gl.useProgram(program.getProgram()); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); |
| gl.bindImageTexture(0 /* unit */, texture, level /* level */, GL_FALSE /* layered */, 0 /* layer */, |
| GL_WRITE_ONLY, convFormat); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture"); |
| gl.uniform1i(1, 0 /* image_unit */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); |
| gl.dispatchCompute(width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute"); |
| gl.memoryBarrier(GL_ALL_BARRIER_BITS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier"); |
| } |
| else |
| { |
| mLog << "Compute shader compilation failed (writing) for target: " << target << ", format: " << format |
| << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog |
| << ", shaderSource: " << shader.c_str() << " - "; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /** Setup depth compare mode and compare function for depth texture |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param texture Texture object |
| */ |
| void SparseTexture2LookupTestCase::setupDepthMode(const Functions& gl, GLint target, GLuint& texture) |
| { |
| Texture::Bind(gl, texture, target); |
| gl.texParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); |
| gl.texParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); |
| } |
| |
| /** Verify if data stored in texture is as expected |
| * |
| * @param gl GL API functions |
| * @param target Target for which texture is binded |
| * @param format Texture internal format |
| * @param texture Texture object |
| * @param level Texture mipmap level |
| * @param funcToken Lookup function tokenize structure |
| * |
| * @return Returns true if data is as expected, false if not, throws an exception if error occurred. |
| */ |
| bool SparseTexture2LookupTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format, |
| GLuint& texture, GLint level, FunctionToken& funcToken) |
| { |
| mLog << "Verify Lookup Texture Data [function: " << funcToken.name << ", level: " << level << "] - "; |
| |
| if (level > mState.levels - 1) |
| TCU_FAIL("Invalid level"); |
| |
| GLint width; |
| GLint height; |
| GLint depth; |
| SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth); |
| |
| //Committed region is limited to 1/2 of width |
| GLint widthCommitted = width / 2; |
| |
| if (widthCommitted == 0 || height == 0 || depth < mState.minDepth) |
| return true; |
| |
| bool result = true; |
| |
| if (target == GL_TEXTURE_CUBE_MAP) |
| depth = depth * 6; |
| |
| GLint texSize = width * height * depth; |
| |
| std::vector<GLubyte> vecExpData; |
| std::vector<GLubyte> vecOutData; |
| vecExpData.resize(texSize); |
| vecOutData.resize(texSize); |
| GLubyte* exp_data = vecExpData.data(); |
| GLubyte* out_data = vecOutData.data(); |
| |
| // Expected data is 255 because |
| deMemset(exp_data, 255, texSize); |
| |
| // Make token copy to work on |
| FunctionToken f = funcToken; |
| |
| // Create verifying texture |
| GLint verifyTarget; |
| if (target == GL_TEXTURE_2D_MULTISAMPLE) |
| verifyTarget = GL_TEXTURE_2D; |
| else |
| verifyTarget = GL_TEXTURE_2D_ARRAY; |
| |
| GLuint verifyTexture; |
| Texture::Generate(gl, verifyTexture); |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage"); |
| |
| for (int sample = 0; sample < mState.samples; ++sample) |
| { |
| deMemset(out_data, 0, texSize); |
| |
| Texture::Bind(gl, verifyTexture, verifyTarget); |
| Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, depth, GL_RED, GL_UNSIGNED_BYTE, |
| (GLvoid*)out_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage"); |
| |
| std::string shader = st2_compute_lookupVerify; |
| |
| // Adjust shader source to texture format |
| TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f); |
| |
| replaceToken("<FUNCTION>", f.name.c_str(), shader); |
| replaceToken("<ARGUMENTS>", f.arguments.c_str(), shader); |
| |
| replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), shader); |
| replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader); |
| replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), shader); |
| replaceToken("<LOD>", s.lod.c_str(), shader); |
| replaceToken("<LOD_DEF>", s.lodDef.c_str(), shader); |
| replaceToken("<COORD_TYPE>", s.coordType.c_str(), shader); |
| replaceToken("<ICOORD_TYPE>", s.iCoordType.c_str(), shader); |
| replaceToken("<COORD_DEF>", s.coordDef.c_str(), shader); |
| replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader); |
| replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader); |
| replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader); |
| replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader); |
|