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 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 input->name_offset, input->name_length); | 1072 input->name_offset, input->name_length); |
1067 ASSERT_TRUE(name_buf != NULL); | 1073 ASSERT_TRUE(name_buf != NULL); |
1068 std::string name(name_buf, input->name_length); | 1074 std::string name(name_buf, input->name_length); |
1069 EXPECT_STREQ(expected.good_name, name.c_str()); | 1075 EXPECT_STREQ(expected.good_name, name.c_str()); |
1070 ++input; | 1076 ++input; |
1071 } | 1077 } |
1072 EXPECT_EQ(header->num_attribs + header->num_uniforms, | 1078 EXPECT_EQ(header->num_attribs + header->num_uniforms, |
1073 static_cast<uint32>(input - inputs)); | 1079 static_cast<uint32>(input - inputs)); |
1074 } | 1080 } |
1075 | 1081 |
| 1082 TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksNone) { |
| 1083 CommonDecoder::Bucket bucket; |
| 1084 const Program* program = manager_.GetProgram(kClientProgramId); |
| 1085 ASSERT_TRUE(program != NULL); |
| 1086 // The program's previous link failed. |
| 1087 EXPECT_CALL(*(gl_.get()), |
| 1088 GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) |
| 1089 .WillOnce(SetArgPointee<2>(GL_FALSE)) |
| 1090 .RetiresOnSaturation(); |
| 1091 EXPECT_TRUE(program->GetUniformBlocks(&bucket)); |
| 1092 EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size()); |
| 1093 UniformBlocksHeader* header = |
| 1094 bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader)); |
| 1095 EXPECT_TRUE(header != NULL); |
| 1096 EXPECT_EQ(0u, header->num_uniform_blocks); |
| 1097 // Zero uniform blocks. |
| 1098 EXPECT_CALL(*(gl_.get()), |
| 1099 GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) |
| 1100 .WillOnce(SetArgPointee<2>(GL_TRUE)) |
| 1101 .RetiresOnSaturation(); |
| 1102 EXPECT_CALL(*(gl_.get()), |
| 1103 GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _)) |
| 1104 .WillOnce(SetArgPointee<2>(0)) |
| 1105 .RetiresOnSaturation(); |
| 1106 EXPECT_TRUE(program->GetUniformBlocks(&bucket)); |
| 1107 EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size()); |
| 1108 header = |
| 1109 bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader)); |
| 1110 EXPECT_TRUE(header != NULL); |
| 1111 EXPECT_EQ(0u, header->num_uniform_blocks); |
| 1112 } |
| 1113 |
| 1114 TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksValid) { |
| 1115 CommonDecoder::Bucket bucket; |
| 1116 const Program* program = manager_.GetProgram(kClientProgramId); |
| 1117 ASSERT_TRUE(program != NULL); |
| 1118 struct Data { |
| 1119 UniformBlocksHeader header; |
| 1120 UniformBlockInfo entry[2]; |
| 1121 char name0[4]; |
| 1122 uint32_t indices0[2]; |
| 1123 char name1[8]; |
| 1124 uint32_t indices1[1]; |
| 1125 }; |
| 1126 Data data; |
| 1127 // The names needs to be of size 4*k-1 to avoid padding in the struct Data. |
| 1128 // This is a testing only problem. |
| 1129 const char* kName[] = { "cow", "chicken" }; |
| 1130 const uint32_t kIndices0[] = { 1, 2 }; |
| 1131 const uint32_t kIndices1[] = { 3 }; |
| 1132 const uint32_t* kIndices[] = { kIndices0, kIndices1 }; |
| 1133 data.header.num_uniform_blocks = 2; |
| 1134 data.entry[0].binding = 0; |
| 1135 data.entry[0].data_size = 8; |
| 1136 data.entry[0].name_offset = ComputeOffset(&data, data.name0); |
| 1137 data.entry[0].name_length = arraysize(data.name0); |
| 1138 data.entry[0].active_uniforms = arraysize(data.indices0); |
| 1139 data.entry[0].active_uniform_offset = ComputeOffset(&data, data.indices0); |
| 1140 data.entry[0].referenced_by_vertex_shader = static_cast<uint32_t>(true); |
| 1141 data.entry[0].referenced_by_fragment_shader = static_cast<uint32_t>(false); |
| 1142 data.entry[1].binding = 1; |
| 1143 data.entry[1].data_size = 4; |
| 1144 data.entry[1].name_offset = ComputeOffset(&data, data.name1); |
| 1145 data.entry[1].name_length = arraysize(data.name1); |
| 1146 data.entry[1].active_uniforms = arraysize(data.indices1); |
| 1147 data.entry[1].active_uniform_offset = ComputeOffset(&data, data.indices1); |
| 1148 data.entry[1].referenced_by_vertex_shader = static_cast<uint32_t>(false); |
| 1149 data.entry[1].referenced_by_fragment_shader = static_cast<uint32_t>(true); |
| 1150 memcpy(data.name0, kName[0], arraysize(data.name0)); |
| 1151 data.indices0[0] = kIndices[0][0]; |
| 1152 data.indices0[1] = kIndices[0][1]; |
| 1153 memcpy(data.name1, kName[1], arraysize(data.name1)); |
| 1154 data.indices1[0] = kIndices[1][0]; |
| 1155 |
| 1156 EXPECT_CALL(*(gl_.get()), |
| 1157 GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) |
| 1158 .WillOnce(SetArgPointee<2>(GL_TRUE)) |
| 1159 .RetiresOnSaturation(); |
| 1160 EXPECT_CALL(*(gl_.get()), |
| 1161 GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _)) |
| 1162 .WillOnce(SetArgPointee<2>(data.header.num_uniform_blocks)) |
| 1163 .RetiresOnSaturation(); |
| 1164 EXPECT_CALL(*(gl_.get()), |
| 1165 GetProgramiv(kServiceProgramId, |
| 1166 GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, _)) |
| 1167 .WillOnce(SetArgPointee<2>( |
| 1168 std::max(strlen(kName[0]), strlen(kName[1]) + 1))) |
| 1169 .RetiresOnSaturation(); |
| 1170 for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) { |
| 1171 EXPECT_CALL(*(gl_.get()), |
| 1172 GetActiveUniformBlockiv( |
| 1173 kServiceProgramId, ii, GL_UNIFORM_BLOCK_BINDING, _)) |
| 1174 .WillOnce(SetArgPointee<3>(data.entry[ii].binding)) |
| 1175 .RetiresOnSaturation(); |
| 1176 EXPECT_CALL(*(gl_.get()), |
| 1177 GetActiveUniformBlockiv( |
| 1178 kServiceProgramId, ii, GL_UNIFORM_BLOCK_DATA_SIZE, _)) |
| 1179 .WillOnce(SetArgPointee<3>(data.entry[ii].data_size)) |
| 1180 .RetiresOnSaturation(); |
| 1181 EXPECT_CALL(*(gl_.get()), |
| 1182 GetActiveUniformBlockiv( |
| 1183 kServiceProgramId, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, _)) |
| 1184 .WillOnce(SetArgPointee<3>(data.entry[ii].name_length)) |
| 1185 .RetiresOnSaturation(); |
| 1186 EXPECT_CALL(*(gl_.get()), |
| 1187 GetActiveUniformBlockName( |
| 1188 kServiceProgramId, ii, data.entry[ii].name_length, _, _)) |
| 1189 .WillOnce(DoAll( |
| 1190 SetArgPointee<3>(strlen(kName[ii])), |
| 1191 SetArrayArgument<4>( |
| 1192 kName[ii], kName[ii] + data.entry[ii].name_length))) |
| 1193 .RetiresOnSaturation(); |
| 1194 EXPECT_CALL(*(gl_.get()), |
| 1195 GetActiveUniformBlockiv( |
| 1196 kServiceProgramId, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _)) |
| 1197 .WillOnce(SetArgPointee<3>(data.entry[ii].active_uniforms)) |
| 1198 .RetiresOnSaturation(); |
| 1199 EXPECT_CALL(*(gl_.get()), |
| 1200 GetActiveUniformBlockiv( |
| 1201 kServiceProgramId, ii, |
| 1202 GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, _)) |
| 1203 .WillOnce(SetArgPointee<3>(data.entry[ii].referenced_by_vertex_shader)) |
| 1204 .RetiresOnSaturation(); |
| 1205 EXPECT_CALL(*(gl_.get()), |
| 1206 GetActiveUniformBlockiv( |
| 1207 kServiceProgramId, ii, |
| 1208 GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, _)) |
| 1209 .WillOnce(SetArgPointee<3>( |
| 1210 data.entry[ii].referenced_by_fragment_shader)) |
| 1211 .RetiresOnSaturation(); |
| 1212 } |
| 1213 for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) { |
| 1214 EXPECT_CALL(*(gl_.get()), |
| 1215 GetActiveUniformBlockiv( |
| 1216 kServiceProgramId, ii, |
| 1217 GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, _)) |
| 1218 .WillOnce(SetArrayArgument<3>( |
| 1219 kIndices[ii], kIndices[ii] + data.entry[ii].active_uniforms)) |
| 1220 .RetiresOnSaturation(); |
| 1221 } |
| 1222 program->GetUniformBlocks(&bucket); |
| 1223 EXPECT_EQ(sizeof(Data), bucket.size()); |
| 1224 Data* bucket_data = bucket.GetDataAs<Data*>(0, sizeof(Data)); |
| 1225 EXPECT_TRUE(bucket_data != NULL); |
| 1226 EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data))); |
| 1227 } |
| 1228 |
1076 // Some drivers optimize out unused uniform array elements, so their | 1229 // Some drivers optimize out unused uniform array elements, so their |
1077 // location would be -1. | 1230 // location would be -1. |
1078 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { | 1231 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { |
1079 CommonDecoder::Bucket bucket; | 1232 CommonDecoder::Bucket bucket; |
1080 const Program* program = manager_.GetProgram(kClientProgramId); | 1233 const Program* program = manager_.GetProgram(kClientProgramId); |
1081 ASSERT_TRUE(program != NULL); | 1234 ASSERT_TRUE(program != NULL); |
1082 // Emulate the situation that only the first element has a valid location. | 1235 // Emulate the situation that only the first element has a valid location. |
1083 // TODO(zmo): Don't assume these are in order. | 1236 // TODO(zmo): Don't assume these are in order. |
1084 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { | 1237 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { |
1085 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( | 1238 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1710 } | 1863 } |
1711 | 1864 |
1712 void SetExpectationsForSuccessCompile( | 1865 void SetExpectationsForSuccessCompile( |
1713 const Shader* shader) { | 1866 const Shader* shader) { |
1714 const GLuint shader_id = shader->service_id(); | 1867 const GLuint shader_id = shader->service_id(); |
1715 const char* src = shader->source().c_str(); | 1868 const char* src = shader->source().c_str(); |
1716 EXPECT_CALL(*gl_.get(), | 1869 EXPECT_CALL(*gl_.get(), |
1717 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); | 1870 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
1718 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); | 1871 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
1719 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1872 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
1720 .WillOnce(SetArgumentPointee<2>(GL_TRUE)); | 1873 .WillOnce(SetArgPointee<2>(GL_TRUE)); |
1721 } | 1874 } |
1722 | 1875 |
1723 void SetExpectationsForNoCompile(const Shader* shader) { | 1876 void SetExpectationsForNoCompile(const Shader* shader) { |
1724 const GLuint shader_id = shader->service_id(); | 1877 const GLuint shader_id = shader->service_id(); |
1725 const char* src = shader->source().c_str(); | 1878 const char* src = shader->source().c_str(); |
1726 EXPECT_CALL(*gl_.get(), | 1879 EXPECT_CALL(*gl_.get(), |
1727 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); | 1880 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); |
1728 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); | 1881 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); |
1729 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1882 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
1730 .Times(0); | 1883 .Times(0); |
1731 } | 1884 } |
1732 | 1885 |
1733 void SetExpectationsForErrorCompile(const Shader* shader) { | 1886 void SetExpectationsForErrorCompile(const Shader* shader) { |
1734 const GLuint shader_id = shader->service_id(); | 1887 const GLuint shader_id = shader->service_id(); |
1735 const char* src = shader->source().c_str(); | 1888 const char* src = shader->source().c_str(); |
1736 EXPECT_CALL(*gl_.get(), | 1889 EXPECT_CALL(*gl_.get(), |
1737 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); | 1890 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
1738 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); | 1891 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
1739 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1892 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
1740 .WillOnce(SetArgumentPointee<2>(GL_FALSE)); | 1893 .WillOnce(SetArgPointee<2>(GL_FALSE)); |
1741 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) | 1894 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) |
1742 .WillOnce(SetArgumentPointee<2>(0)); | 1895 .WillOnce(SetArgPointee<2>(0)); |
1743 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) | 1896 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) |
1744 .Times(1); | 1897 .Times(1); |
1745 } | 1898 } |
1746 | 1899 |
1747 scoped_ptr<MockProgramCache> cache_; | 1900 scoped_ptr<MockProgramCache> cache_; |
1748 ProgramManager manager_; | 1901 ProgramManager manager_; |
1749 | 1902 |
1750 Shader* vertex_shader_; | 1903 Shader* vertex_shader_; |
1751 Shader* fragment_shader_; | 1904 Shader* fragment_shader_; |
1752 Program* program_; | 1905 Program* program_; |
(...skipping 27 matching lines...) Expand all Loading... |
1780 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); | 1933 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); |
1781 SetExpectationsForNotCachingProgram(); | 1934 SetExpectationsForNotCachingProgram(); |
1782 SetExpectationsForProgramLoadSuccess(); | 1935 SetExpectationsForProgramLoadSuccess(); |
1783 | 1936 |
1784 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, | 1937 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, |
1785 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); | 1938 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); |
1786 } | 1939 } |
1787 | 1940 |
1788 } // namespace gles2 | 1941 } // namespace gles2 |
1789 } // namespace gpu | 1942 } // namespace gpu |
OLD | NEW |