OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/program_manager.h" | 5 #include "gpu/command_buffer/service/program_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "ui/gl/gl_mock.h" | 21 #include "ui/gl/gl_mock.h" |
22 | 22 |
23 using ::testing::_; | 23 using ::testing::_; |
24 using ::testing::DoAll; | 24 using ::testing::DoAll; |
25 using ::testing::InSequence; | 25 using ::testing::InSequence; |
26 using ::testing::MatcherCast; | 26 using ::testing::MatcherCast; |
27 using ::testing::Pointee; | 27 using ::testing::Pointee; |
28 using ::testing::Return; | 28 using ::testing::Return; |
29 using ::testing::ReturnRef; | 29 using ::testing::ReturnRef; |
30 using ::testing::SetArrayArgument; | 30 using ::testing::SetArrayArgument; |
31 using ::testing::SetArgumentPointee; | 31 using ::testing::SetArgPointee; |
32 using ::testing::StrEq; | 32 using ::testing::StrEq; |
33 | 33 |
34 namespace gpu { | 34 namespace gpu { |
35 namespace gles2 { | 35 namespace gles2 { |
36 | 36 |
37 namespace { | 37 namespace { |
38 const uint32 kMaxVaryingVectors = 8; | 38 const uint32 kMaxVaryingVectors = 8; |
39 | 39 |
40 void ShaderCacheCb(const std::string& key, const std::string& shader) {} | 40 void ShaderCacheCb(const std::string& key, const std::string& shader) {} |
| 41 |
| 42 uint32 ComputeOffset(const void* start, const void* position) { |
| 43 return static_cast<const uint8*>(position) - |
| 44 static_cast<const uint8*>(start); |
| 45 } |
| 46 |
41 } // namespace anonymous | 47 } // namespace anonymous |
42 | 48 |
43 class ProgramManagerTest : public GpuServiceTest { | 49 class ProgramManagerTest : public GpuServiceTest { |
44 public: | 50 public: |
45 ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { } | 51 ProgramManagerTest() : manager_(NULL, kMaxVaryingVectors) { } |
46 ~ProgramManagerTest() override { manager_.Destroy(false); } | 52 ~ProgramManagerTest() override { manager_.Destroy(false); } |
47 | 53 |
48 protected: | 54 protected: |
49 ProgramManager manager_; | 55 ProgramManager manager_; |
50 }; | 56 }; |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 typedef struct { | 213 typedef struct { |
208 GLenum type; | 214 GLenum type; |
209 GLint size; | 215 GLint size; |
210 GLenum precision; | 216 GLenum precision; |
211 bool static_use; | 217 bool static_use; |
212 std::string name; | 218 std::string name; |
213 VarCategory category; | 219 VarCategory category; |
214 } VarInfo; | 220 } VarInfo; |
215 | 221 |
216 void SetUp() override { | 222 void SetUp() override { |
217 GpuServiceTest::SetUp(); | 223 // Need to be at leat 3.1 for UniformBlock related GL APIs. |
| 224 GpuServiceTest::SetUpWithGLVersion("3.1", NULL); |
218 | 225 |
219 SetupDefaultShaderExpectations(); | 226 SetupDefaultShaderExpectations(); |
220 | 227 |
221 Shader* vertex_shader = shader_manager_.CreateShader( | 228 Shader* vertex_shader = shader_manager_.CreateShader( |
222 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); | 229 kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); |
223 Shader* fragment_shader = | 230 Shader* fragment_shader = |
224 shader_manager_.CreateShader( | 231 shader_manager_.CreateShader( |
225 kFragmentShaderClientId, kFragmentShaderServiceId, | 232 kFragmentShaderClientId, kFragmentShaderServiceId, |
226 GL_FRAGMENT_SHADER); | 233 GL_FRAGMENT_SHADER); |
227 ASSERT_TRUE(vertex_shader != NULL); | 234 ASSERT_TRUE(vertex_shader != NULL); |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 input->name_offset, input->name_length); | 1073 input->name_offset, input->name_length); |
1067 ASSERT_TRUE(name_buf != NULL); | 1074 ASSERT_TRUE(name_buf != NULL); |
1068 std::string name(name_buf, input->name_length); | 1075 std::string name(name_buf, input->name_length); |
1069 EXPECT_STREQ(expected.good_name, name.c_str()); | 1076 EXPECT_STREQ(expected.good_name, name.c_str()); |
1070 ++input; | 1077 ++input; |
1071 } | 1078 } |
1072 EXPECT_EQ(header->num_attribs + header->num_uniforms, | 1079 EXPECT_EQ(header->num_attribs + header->num_uniforms, |
1073 static_cast<uint32>(input - inputs)); | 1080 static_cast<uint32>(input - inputs)); |
1074 } | 1081 } |
1075 | 1082 |
| 1083 TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksNone) { |
| 1084 CommonDecoder::Bucket bucket; |
| 1085 const Program* program = manager_.GetProgram(kClientProgramId); |
| 1086 ASSERT_TRUE(program != NULL); |
| 1087 // The program's previous link failed. |
| 1088 EXPECT_CALL(*(gl_.get()), |
| 1089 GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) |
| 1090 .WillOnce(SetArgPointee<2>(GL_FALSE)) |
| 1091 .RetiresOnSaturation(); |
| 1092 EXPECT_TRUE(program->GetUniformBlocks(&bucket)); |
| 1093 EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size()); |
| 1094 UniformBlocksHeader* header = |
| 1095 bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader)); |
| 1096 EXPECT_TRUE(header != NULL); |
| 1097 EXPECT_EQ(0u, header->num_uniform_blocks); |
| 1098 // Zero uniform blocks. |
| 1099 EXPECT_CALL(*(gl_.get()), |
| 1100 GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) |
| 1101 .WillOnce(SetArgPointee<2>(GL_TRUE)) |
| 1102 .RetiresOnSaturation(); |
| 1103 EXPECT_CALL(*(gl_.get()), |
| 1104 GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _)) |
| 1105 .WillOnce(SetArgPointee<2>(0)) |
| 1106 .RetiresOnSaturation(); |
| 1107 EXPECT_TRUE(program->GetUniformBlocks(&bucket)); |
| 1108 EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size()); |
| 1109 header = |
| 1110 bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader)); |
| 1111 EXPECT_TRUE(header != NULL); |
| 1112 EXPECT_EQ(0u, header->num_uniform_blocks); |
| 1113 } |
| 1114 |
| 1115 TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksValid) { |
| 1116 CommonDecoder::Bucket bucket; |
| 1117 const Program* program = manager_.GetProgram(kClientProgramId); |
| 1118 ASSERT_TRUE(program != NULL); |
| 1119 struct Data { |
| 1120 UniformBlocksHeader header; |
| 1121 UniformBlockInfo entry[2]; |
| 1122 char name0[4]; |
| 1123 uint32_t indices0[2]; |
| 1124 char name1[8]; |
| 1125 uint32_t indices1[1]; |
| 1126 }; |
| 1127 Data data; |
| 1128 // The names needs to be of size 4*k-1 to avoid padding in the struct Data. |
| 1129 // This is a testing only problem. |
| 1130 const char* kName[] = { "cow", "chicken" }; |
| 1131 const uint32_t kIndices0[] = { 1, 2 }; |
| 1132 const uint32_t kIndices1[] = { 3 }; |
| 1133 const uint32_t* kIndices[] = { kIndices0, kIndices1 }; |
| 1134 data.header.num_uniform_blocks = 2; |
| 1135 data.entry[0].binding = 0; |
| 1136 data.entry[0].data_size = 8; |
| 1137 data.entry[0].name_offset = ComputeOffset(&data, data.name0); |
| 1138 data.entry[0].name_length = arraysize(data.name0); |
| 1139 data.entry[0].active_uniforms = arraysize(data.indices0); |
| 1140 data.entry[0].active_uniform_offset = ComputeOffset(&data, data.indices0); |
| 1141 data.entry[0].referenced_by_vertex_shader = static_cast<uint32_t>(true); |
| 1142 data.entry[0].referenced_by_fragment_shader = static_cast<uint32_t>(false); |
| 1143 data.entry[1].binding = 1; |
| 1144 data.entry[1].data_size = 4; |
| 1145 data.entry[1].name_offset = ComputeOffset(&data, data.name1); |
| 1146 data.entry[1].name_length = arraysize(data.name1); |
| 1147 data.entry[1].active_uniforms = arraysize(data.indices1); |
| 1148 data.entry[1].active_uniform_offset = ComputeOffset(&data, data.indices1); |
| 1149 data.entry[1].referenced_by_vertex_shader = static_cast<uint32_t>(false); |
| 1150 data.entry[1].referenced_by_fragment_shader = static_cast<uint32_t>(true); |
| 1151 memcpy(data.name0, kName[0], arraysize(data.name0)); |
| 1152 data.indices0[0] = kIndices[0][0]; |
| 1153 data.indices0[1] = kIndices[0][1]; |
| 1154 memcpy(data.name1, kName[1], arraysize(data.name1)); |
| 1155 data.indices1[0] = kIndices[1][0]; |
| 1156 |
| 1157 EXPECT_CALL(*(gl_.get()), |
| 1158 GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) |
| 1159 .WillOnce(SetArgPointee<2>(GL_TRUE)) |
| 1160 .RetiresOnSaturation(); |
| 1161 EXPECT_CALL(*(gl_.get()), |
| 1162 GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _)) |
| 1163 .WillOnce(SetArgPointee<2>(data.header.num_uniform_blocks)) |
| 1164 .RetiresOnSaturation(); |
| 1165 EXPECT_CALL(*(gl_.get()), |
| 1166 GetProgramiv(kServiceProgramId, |
| 1167 GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, _)) |
| 1168 .WillOnce(SetArgPointee<2>( |
| 1169 1 + std::max(strlen(kName[0]), strlen(kName[1])))) |
| 1170 .RetiresOnSaturation(); |
| 1171 for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) { |
| 1172 EXPECT_CALL(*(gl_.get()), |
| 1173 GetActiveUniformBlockiv( |
| 1174 kServiceProgramId, ii, GL_UNIFORM_BLOCK_BINDING, _)) |
| 1175 .WillOnce(SetArgPointee<3>(data.entry[ii].binding)) |
| 1176 .RetiresOnSaturation(); |
| 1177 EXPECT_CALL(*(gl_.get()), |
| 1178 GetActiveUniformBlockiv( |
| 1179 kServiceProgramId, ii, GL_UNIFORM_BLOCK_DATA_SIZE, _)) |
| 1180 .WillOnce(SetArgPointee<3>(data.entry[ii].data_size)) |
| 1181 .RetiresOnSaturation(); |
| 1182 EXPECT_CALL(*(gl_.get()), |
| 1183 GetActiveUniformBlockiv( |
| 1184 kServiceProgramId, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, _)) |
| 1185 .WillOnce(SetArgPointee<3>(data.entry[ii].name_length)) |
| 1186 .RetiresOnSaturation(); |
| 1187 EXPECT_CALL(*(gl_.get()), |
| 1188 GetActiveUniformBlockName( |
| 1189 kServiceProgramId, ii, data.entry[ii].name_length, _, _)) |
| 1190 .WillOnce(DoAll( |
| 1191 SetArgPointee<3>(strlen(kName[ii])), |
| 1192 SetArrayArgument<4>( |
| 1193 kName[ii], kName[ii] + data.entry[ii].name_length))) |
| 1194 .RetiresOnSaturation(); |
| 1195 EXPECT_CALL(*(gl_.get()), |
| 1196 GetActiveUniformBlockiv( |
| 1197 kServiceProgramId, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _)) |
| 1198 .WillOnce(SetArgPointee<3>(data.entry[ii].active_uniforms)) |
| 1199 .RetiresOnSaturation(); |
| 1200 EXPECT_CALL(*(gl_.get()), |
| 1201 GetActiveUniformBlockiv( |
| 1202 kServiceProgramId, ii, |
| 1203 GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, _)) |
| 1204 .WillOnce(SetArgPointee<3>(data.entry[ii].referenced_by_vertex_shader)) |
| 1205 .RetiresOnSaturation(); |
| 1206 EXPECT_CALL(*(gl_.get()), |
| 1207 GetActiveUniformBlockiv( |
| 1208 kServiceProgramId, ii, |
| 1209 GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, _)) |
| 1210 .WillOnce(SetArgPointee<3>( |
| 1211 data.entry[ii].referenced_by_fragment_shader)) |
| 1212 .RetiresOnSaturation(); |
| 1213 } |
| 1214 for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) { |
| 1215 EXPECT_CALL(*(gl_.get()), |
| 1216 GetActiveUniformBlockiv( |
| 1217 kServiceProgramId, ii, |
| 1218 GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, _)) |
| 1219 .WillOnce(SetArrayArgument<3>( |
| 1220 kIndices[ii], kIndices[ii] + data.entry[ii].active_uniforms)) |
| 1221 .RetiresOnSaturation(); |
| 1222 } |
| 1223 program->GetUniformBlocks(&bucket); |
| 1224 EXPECT_EQ(sizeof(Data), bucket.size()); |
| 1225 Data* bucket_data = bucket.GetDataAs<Data*>(0, sizeof(Data)); |
| 1226 EXPECT_TRUE(bucket_data != NULL); |
| 1227 EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data))); |
| 1228 } |
| 1229 |
1076 // Some drivers optimize out unused uniform array elements, so their | 1230 // Some drivers optimize out unused uniform array elements, so their |
1077 // location would be -1. | 1231 // location would be -1. |
1078 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { | 1232 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { |
1079 CommonDecoder::Bucket bucket; | 1233 CommonDecoder::Bucket bucket; |
1080 const Program* program = manager_.GetProgram(kClientProgramId); | 1234 const Program* program = manager_.GetProgram(kClientProgramId); |
1081 ASSERT_TRUE(program != NULL); | 1235 ASSERT_TRUE(program != NULL); |
1082 // Emulate the situation that only the first element has a valid location. | 1236 // Emulate the situation that only the first element has a valid location. |
1083 // TODO(zmo): Don't assume these are in order. | 1237 // TODO(zmo): Don't assume these are in order. |
1084 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { | 1238 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { |
1085 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( | 1239 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1710 } | 1864 } |
1711 | 1865 |
1712 void SetExpectationsForSuccessCompile( | 1866 void SetExpectationsForSuccessCompile( |
1713 const Shader* shader) { | 1867 const Shader* shader) { |
1714 const GLuint shader_id = shader->service_id(); | 1868 const GLuint shader_id = shader->service_id(); |
1715 const char* src = shader->source().c_str(); | 1869 const char* src = shader->source().c_str(); |
1716 EXPECT_CALL(*gl_.get(), | 1870 EXPECT_CALL(*gl_.get(), |
1717 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); | 1871 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
1718 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); | 1872 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
1719 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1873 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
1720 .WillOnce(SetArgumentPointee<2>(GL_TRUE)); | 1874 .WillOnce(SetArgPointee<2>(GL_TRUE)); |
1721 } | 1875 } |
1722 | 1876 |
1723 void SetExpectationsForNoCompile(const Shader* shader) { | 1877 void SetExpectationsForNoCompile(const Shader* shader) { |
1724 const GLuint shader_id = shader->service_id(); | 1878 const GLuint shader_id = shader->service_id(); |
1725 const char* src = shader->source().c_str(); | 1879 const char* src = shader->source().c_str(); |
1726 EXPECT_CALL(*gl_.get(), | 1880 EXPECT_CALL(*gl_.get(), |
1727 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); | 1881 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); |
1728 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); | 1882 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); |
1729 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1883 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
1730 .Times(0); | 1884 .Times(0); |
1731 } | 1885 } |
1732 | 1886 |
1733 void SetExpectationsForErrorCompile(const Shader* shader) { | 1887 void SetExpectationsForErrorCompile(const Shader* shader) { |
1734 const GLuint shader_id = shader->service_id(); | 1888 const GLuint shader_id = shader->service_id(); |
1735 const char* src = shader->source().c_str(); | 1889 const char* src = shader->source().c_str(); |
1736 EXPECT_CALL(*gl_.get(), | 1890 EXPECT_CALL(*gl_.get(), |
1737 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); | 1891 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
1738 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); | 1892 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
1739 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1893 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
1740 .WillOnce(SetArgumentPointee<2>(GL_FALSE)); | 1894 .WillOnce(SetArgPointee<2>(GL_FALSE)); |
1741 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) | 1895 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) |
1742 .WillOnce(SetArgumentPointee<2>(0)); | 1896 .WillOnce(SetArgPointee<2>(0)); |
1743 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) | 1897 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) |
1744 .Times(1); | 1898 .Times(1); |
1745 } | 1899 } |
1746 | 1900 |
1747 scoped_ptr<MockProgramCache> cache_; | 1901 scoped_ptr<MockProgramCache> cache_; |
1748 ProgramManager manager_; | 1902 ProgramManager manager_; |
1749 | 1903 |
1750 Shader* vertex_shader_; | 1904 Shader* vertex_shader_; |
1751 Shader* fragment_shader_; | 1905 Shader* fragment_shader_; |
1752 Program* program_; | 1906 Program* program_; |
(...skipping 27 matching lines...) Expand all Loading... |
1780 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); | 1934 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); |
1781 SetExpectationsForNotCachingProgram(); | 1935 SetExpectationsForNotCachingProgram(); |
1782 SetExpectationsForProgramLoadSuccess(); | 1936 SetExpectationsForProgramLoadSuccess(); |
1783 | 1937 |
1784 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, | 1938 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, |
1785 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); | 1939 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); |
1786 } | 1940 } |
1787 | 1941 |
1788 } // namespace gles2 | 1942 } // namespace gles2 |
1789 } // namespace gpu | 1943 } // namespace gpu |
OLD | NEW |