| 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 program->GetUniformBlocks(&bucket); |
| 1092 EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size()); |
| 1093 UniformBlocksHeader* header = |
| 1094 bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader)); |
| 1095 ASSERT_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 program->GetUniformBlocks(&bucket); |
| 1107 EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size()); |
| 1108 header = |
| 1109 bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader)); |
| 1110 ASSERT_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 for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) { |
| 1165 EXPECT_CALL(*(gl_.get()), |
| 1166 GetActiveUniformBlockiv( |
| 1167 kServiceProgramId, ii, GL_UNIFORM_BLOCK_BINDING, _)) |
| 1168 .WillOnce(SetArgPointee<3>(data.entry[ii].binding)) |
| 1169 .RetiresOnSaturation(); |
| 1170 EXPECT_CALL(*(gl_.get()), |
| 1171 GetActiveUniformBlockiv( |
| 1172 kServiceProgramId, ii, GL_UNIFORM_BLOCK_DATA_SIZE, _)) |
| 1173 .WillOnce(SetArgPointee<3>(data.entry[ii].data_size)) |
| 1174 .RetiresOnSaturation(); |
| 1175 EXPECT_CALL(*(gl_.get()), |
| 1176 GetActiveUniformBlockiv( |
| 1177 kServiceProgramId, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, _)) |
| 1178 .WillOnce(SetArgPointee<3>(data.entry[ii].name_length)) |
| 1179 .RetiresOnSaturation(); |
| 1180 EXPECT_CALL(*(gl_.get()), |
| 1181 GetActiveUniformBlockiv( |
| 1182 kServiceProgramId, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _)) |
| 1183 .WillOnce(SetArgPointee<3>(data.entry[ii].active_uniforms)) |
| 1184 .RetiresOnSaturation(); |
| 1185 EXPECT_CALL(*(gl_.get()), |
| 1186 GetActiveUniformBlockiv( |
| 1187 kServiceProgramId, ii, |
| 1188 GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, _)) |
| 1189 .WillOnce(SetArgPointee<3>(data.entry[ii].referenced_by_vertex_shader)) |
| 1190 .RetiresOnSaturation(); |
| 1191 EXPECT_CALL(*(gl_.get()), |
| 1192 GetActiveUniformBlockiv( |
| 1193 kServiceProgramId, ii, |
| 1194 GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, _)) |
| 1195 .WillOnce(SetArgPointee<3>( |
| 1196 data.entry[ii].referenced_by_fragment_shader)) |
| 1197 .RetiresOnSaturation(); |
| 1198 } |
| 1199 for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) { |
| 1200 EXPECT_CALL(*(gl_.get()), |
| 1201 GetActiveUniformBlockName( |
| 1202 kServiceProgramId, ii, data.entry[ii].name_length, _, _)) |
| 1203 .WillOnce(DoAll( |
| 1204 SetArgPointee<3>(strlen(kName[ii])), |
| 1205 SetArrayArgument<4>( |
| 1206 kName[ii], kName[ii] + data.entry[ii].name_length))) |
| 1207 .RetiresOnSaturation(); |
| 1208 EXPECT_CALL(*(gl_.get()), |
| 1209 GetActiveUniformBlockiv( |
| 1210 kServiceProgramId, ii, |
| 1211 GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, _)) |
| 1212 .WillOnce(SetArrayArgument<3>( |
| 1213 kIndices[ii], kIndices[ii] + data.entry[ii].active_uniforms)) |
| 1214 .RetiresOnSaturation(); |
| 1215 } |
| 1216 program->GetUniformBlocks(&bucket); |
| 1217 EXPECT_EQ(sizeof(Data), bucket.size()); |
| 1218 Data* bucket_data = bucket.GetDataAs<Data*>(0, sizeof(Data)); |
| 1219 EXPECT_TRUE(bucket_data != NULL); |
| 1220 EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data))); |
| 1221 } |
| 1222 |
| 1076 // Some drivers optimize out unused uniform array elements, so their | 1223 // Some drivers optimize out unused uniform array elements, so their |
| 1077 // location would be -1. | 1224 // location would be -1. |
| 1078 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { | 1225 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) { |
| 1079 CommonDecoder::Bucket bucket; | 1226 CommonDecoder::Bucket bucket; |
| 1080 const Program* program = manager_.GetProgram(kClientProgramId); | 1227 const Program* program = manager_.GetProgram(kClientProgramId); |
| 1081 ASSERT_TRUE(program != NULL); | 1228 ASSERT_TRUE(program != NULL); |
| 1082 // Emulate the situation that only the first element has a valid location. | 1229 // Emulate the situation that only the first element has a valid location. |
| 1083 // TODO(zmo): Don't assume these are in order. | 1230 // TODO(zmo): Don't assume these are in order. |
| 1084 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { | 1231 for (size_t ii = 0; ii < arraysize(kUniforms); ++ii) { |
| 1085 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( | 1232 Program::UniformInfo* uniform = const_cast<Program::UniformInfo*>( |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 } | 1857 } |
| 1711 | 1858 |
| 1712 void SetExpectationsForSuccessCompile( | 1859 void SetExpectationsForSuccessCompile( |
| 1713 const Shader* shader) { | 1860 const Shader* shader) { |
| 1714 const GLuint shader_id = shader->service_id(); | 1861 const GLuint shader_id = shader->service_id(); |
| 1715 const char* src = shader->source().c_str(); | 1862 const char* src = shader->source().c_str(); |
| 1716 EXPECT_CALL(*gl_.get(), | 1863 EXPECT_CALL(*gl_.get(), |
| 1717 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); | 1864 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
| 1718 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); | 1865 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
| 1719 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1866 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
| 1720 .WillOnce(SetArgumentPointee<2>(GL_TRUE)); | 1867 .WillOnce(SetArgPointee<2>(GL_TRUE)); |
| 1721 } | 1868 } |
| 1722 | 1869 |
| 1723 void SetExpectationsForNoCompile(const Shader* shader) { | 1870 void SetExpectationsForNoCompile(const Shader* shader) { |
| 1724 const GLuint shader_id = shader->service_id(); | 1871 const GLuint shader_id = shader->service_id(); |
| 1725 const char* src = shader->source().c_str(); | 1872 const char* src = shader->source().c_str(); |
| 1726 EXPECT_CALL(*gl_.get(), | 1873 EXPECT_CALL(*gl_.get(), |
| 1727 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); | 1874 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); |
| 1728 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); | 1875 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); |
| 1729 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1876 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
| 1730 .Times(0); | 1877 .Times(0); |
| 1731 } | 1878 } |
| 1732 | 1879 |
| 1733 void SetExpectationsForErrorCompile(const Shader* shader) { | 1880 void SetExpectationsForErrorCompile(const Shader* shader) { |
| 1734 const GLuint shader_id = shader->service_id(); | 1881 const GLuint shader_id = shader->service_id(); |
| 1735 const char* src = shader->source().c_str(); | 1882 const char* src = shader->source().c_str(); |
| 1736 EXPECT_CALL(*gl_.get(), | 1883 EXPECT_CALL(*gl_.get(), |
| 1737 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); | 1884 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
| 1738 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); | 1885 EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
| 1739 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) | 1886 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
| 1740 .WillOnce(SetArgumentPointee<2>(GL_FALSE)); | 1887 .WillOnce(SetArgPointee<2>(GL_FALSE)); |
| 1741 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) | 1888 EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) |
| 1742 .WillOnce(SetArgumentPointee<2>(0)); | 1889 .WillOnce(SetArgPointee<2>(0)); |
| 1743 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) | 1890 EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) |
| 1744 .Times(1); | 1891 .Times(1); |
| 1745 } | 1892 } |
| 1746 | 1893 |
| 1747 scoped_ptr<MockProgramCache> cache_; | 1894 scoped_ptr<MockProgramCache> cache_; |
| 1748 ProgramManager manager_; | 1895 ProgramManager manager_; |
| 1749 | 1896 |
| 1750 Shader* vertex_shader_; | 1897 Shader* vertex_shader_; |
| 1751 Shader* fragment_shader_; | 1898 Shader* fragment_shader_; |
| 1752 Program* program_; | 1899 Program* program_; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1780 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); | 1927 SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); |
| 1781 SetExpectationsForNotCachingProgram(); | 1928 SetExpectationsForNotCachingProgram(); |
| 1782 SetExpectationsForProgramLoadSuccess(); | 1929 SetExpectationsForProgramLoadSuccess(); |
| 1783 | 1930 |
| 1784 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, | 1931 EXPECT_TRUE(program_->Link(NULL, NULL, NULL, |
| 1785 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); | 1932 Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb))); |
| 1786 } | 1933 } |
| 1787 | 1934 |
| 1788 } // namespace gles2 | 1935 } // namespace gles2 |
| 1789 } // namespace gpu | 1936 } // namespace gpu |
| OLD | NEW |