Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: gpu/command_buffer/service/buffer_manager.cc

Issue 1845963003: Make sure we call glBufferData on the same data we store internally. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: "Fixed comment." Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gpu/command_buffer/service/buffer_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/buffer_manager.h" 5 #include "gpu/command_buffer/service/buffer_manager.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 void* Buffer::MappedRange::GetShmPointer() const { 112 void* Buffer::MappedRange::GetShmPointer() const {
113 DCHECK(shm.get()); 113 DCHECK(shm.get());
114 return shm->GetDataAddress(static_cast<unsigned int>(offset), 114 return shm->GetDataAddress(static_cast<unsigned int>(offset),
115 static_cast<unsigned int>(size)); 115 static_cast<unsigned int>(size));
116 } 116 }
117 117
118 Buffer::Buffer(BufferManager* manager, GLuint service_id) 118 Buffer::Buffer(BufferManager* manager, GLuint service_id)
119 : manager_(manager), 119 : manager_(manager),
120 size_(0), 120 size_(0),
121 deleted_(false), 121 deleted_(false),
122 shadowed_(false),
123 is_client_side_array_(false), 122 is_client_side_array_(false),
124 service_id_(service_id), 123 service_id_(service_id),
125 initial_target_(0), 124 initial_target_(0),
126 usage_(GL_STATIC_DRAW) { 125 usage_(GL_STATIC_DRAW) {
127 manager_->StartTracking(this); 126 manager_->StartTracking(this);
128 } 127 }
129 128
130 Buffer::~Buffer() { 129 Buffer::~Buffer() {
131 if (manager_) { 130 if (manager_) {
132 if (manager_->have_context_) { 131 if (manager_->have_context_) {
133 GLuint id = service_id(); 132 GLuint id = service_id();
134 glDeleteBuffersARB(1, &id); 133 glDeleteBuffersARB(1, &id);
135 } 134 }
136 manager_->StopTracking(this); 135 manager_->StopTracking(this);
137 manager_ = NULL; 136 manager_ = NULL;
138 } 137 }
139 } 138 }
140 139
140 const GLvoid* Buffer::StageShadow(bool use_shadow, GLsizeiptr size,
141 const GLvoid* data) {
142 if (use_shadow) {
143 shadow_.resize(size);
piman 2016/04/01 00:09:46 Why the change to std::vector? We never need to ap
David Yen 2016/04/01 17:00:53 The reason I changed it to a vector was to reduce
144 if (data) {
145 memcpy(shadow_.data(), data, size);
146 } else {
147 memset(shadow_.data(), 0, size);
148 }
149 return shadow_.data();
150 } else {
151 shadow_.clear();
152 return data;
153 }
154 }
155
141 void Buffer::SetInfo( 156 void Buffer::SetInfo(
142 GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, 157 GLsizeiptr size, GLenum usage, bool shadow, bool is_client_side_array) {
Ken Russell (switch to Gerrit) 2016/03/31 23:28:04 It might be more clear now to rename "shadow" to "
David Yen 2016/04/01 17:00:53 Done.
143 bool is_client_side_array) {
144 usage_ = usage; 158 usage_ = usage;
145 is_client_side_array_ = is_client_side_array; 159 is_client_side_array_ = is_client_side_array;
146 ClearCache(); 160 ClearCache();
147 if (size != size_ || shadow != shadowed_) { 161
148 shadowed_ = shadow; 162 // Shadow must have been setup already.
149 size_ = size; 163 DCHECK_EQ(shadow_.size(), static_cast<size_t>(shadow ? size : 0u));
150 if (shadowed_) { 164 size_ = size;
151 shadow_.reset(new int8_t[size]); 165
152 } else {
153 shadow_.reset();
154 }
155 }
156 if (shadowed_) {
157 if (data) {
158 memcpy(shadow_.get(), data, size);
159 } else {
160 memset(shadow_.get(), 0, size);
161 }
162 }
163 mapped_range_.reset(nullptr); 166 mapped_range_.reset(nullptr);
164 } 167 }
165 168
166 bool Buffer::CheckRange( 169 bool Buffer::CheckRange(
167 GLintptr offset, GLsizeiptr size) const { 170 GLintptr offset, GLsizeiptr size) const {
168 int32_t end = 0; 171 int32_t end = 0;
169 return offset >= 0 && size >= 0 && 172 return offset >= 0 && size >= 0 &&
170 offset <= std::numeric_limits<int32_t>::max() && 173 offset <= std::numeric_limits<int32_t>::max() &&
171 size <= std::numeric_limits<int32_t>::max() && 174 size <= std::numeric_limits<int32_t>::max() &&
172 SafeAddInt32(offset, size, &end) && end <= size_; 175 SafeAddInt32(offset, size, &end) && end <= size_;
173 } 176 }
174 177
175 bool Buffer::SetRange( 178 bool Buffer::SetRange(
176 GLintptr offset, GLsizeiptr size, const GLvoid * data) { 179 GLintptr offset, GLsizeiptr size, const GLvoid * data) {
177 if (!CheckRange(offset, size)) { 180 if (!CheckRange(offset, size)) {
178 return false; 181 return false;
179 } 182 }
180 if (shadowed_) { 183 if (!shadow_.empty()) {
181 memcpy(shadow_.get() + offset, data, size); 184 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
185 memcpy(shadow_.data() + offset, data, size);
182 ClearCache(); 186 ClearCache();
183 } 187 }
184 return true; 188 return true;
185 } 189 }
186 190
187 const void* Buffer::GetRange( 191 const void* Buffer::GetRange(
188 GLintptr offset, GLsizeiptr size) const { 192 GLintptr offset, GLsizeiptr size) const {
189 if (!shadowed_) { 193 if (shadow_.empty()) {
190 return NULL; 194 return NULL;
191 } 195 }
192 if (!CheckRange(offset, size)) { 196 if (!CheckRange(offset, size)) {
193 return NULL; 197 return NULL;
194 } 198 }
195 return shadow_.get() + offset; 199 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
200 return shadow_.data() + offset;
196 } 201 }
197 202
198 void Buffer::ClearCache() { 203 void Buffer::ClearCache() {
199 range_set_.clear(); 204 range_set_.clear();
200 } 205 }
201 206
202 template <typename T> 207 template <typename T>
203 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, 208 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count,
204 GLuint primitive_restart_index) { 209 GLuint primitive_restart_index) {
205 GLuint max_value = 0; 210 GLuint max_value = 0;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 } 278 }
274 279
275 if (!SafeAddUint32(offset, size, &size)) { 280 if (!SafeAddUint32(offset, size, &size)) {
276 return false; 281 return false;
277 } 282 }
278 283
279 if (size > static_cast<uint32_t>(size_)) { 284 if (size > static_cast<uint32_t>(size_)) {
280 return false; 285 return false;
281 } 286 }
282 287
283 if (!shadowed_) { 288 if (shadow_.empty()) {
284 return false; 289 return false;
285 } 290 }
286 291
287 // Scan the range for the max value and store 292 // Scan the range for the max value and store
288 GLuint max_v = 0; 293 GLuint max_v = 0;
289 switch (type) { 294 switch (type) {
290 case GL_UNSIGNED_BYTE: 295 case GL_UNSIGNED_BYTE:
291 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count, 296 max_v = GetMaxValue<uint8_t>(shadow_.data(), offset, count,
292 primitive_restart_index); 297 primitive_restart_index);
293 break; 298 break;
294 case GL_UNSIGNED_SHORT: 299 case GL_UNSIGNED_SHORT:
295 // Check we are not accessing an odd byte for a 2 byte value. 300 // Check we are not accessing an odd byte for a 2 byte value.
296 if ((offset & 1) != 0) { 301 if ((offset & 1) != 0) {
297 return false; 302 return false;
298 } 303 }
299 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count, 304 max_v = GetMaxValue<uint16_t>(shadow_.data(), offset, count,
300 primitive_restart_index); 305 primitive_restart_index);
301 break; 306 break;
302 case GL_UNSIGNED_INT: 307 case GL_UNSIGNED_INT:
303 // Check we are not accessing a non aligned address for a 4 byte value. 308 // Check we are not accessing a non aligned address for a 4 byte value.
304 if ((offset & 3) != 0) { 309 if ((offset & 3) != 0) {
305 return false; 310 return false;
306 } 311 }
307 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count, 312 max_v = GetMaxValue<uint32_t>(shadow_.data(), offset, count,
308 primitive_restart_index); 313 primitive_restart_index);
309 break; 314 break;
310 default: 315 default:
311 NOTREACHED(); // should never get here by validation. 316 NOTREACHED(); // should never get here by validation.
312 break; 317 break;
313 } 318 }
314 range_set_.insert(std::make_pair(range, max_v)); 319 range_set_.insert(std::make_pair(range, max_v));
315 *max_value = max_v; 320 *max_value = max_v;
316 return true; 321 return true;
317 } 322 }
(...skipping 13 matching lines...) Expand all
331 bool BufferManager::IsUsageClientSideArray(GLenum usage) { 336 bool BufferManager::IsUsageClientSideArray(GLenum usage) {
332 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; 337 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_;
333 } 338 }
334 339
335 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { 340 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() {
336 return feature_info_.get() && 341 return feature_info_.get() &&
337 feature_info_->workarounds() 342 feature_info_->workarounds()
338 .use_non_zero_size_for_client_side_stream_buffers; 343 .use_non_zero_size_for_client_side_stream_buffers;
339 } 344 }
340 345
341 void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, 346 bool BufferManager::UseShadowBuffer(GLenum target, GLenum usage) {
342 GLenum usage, const GLvoid* data) {
343 DCHECK(buffer);
344 memory_type_tracker_->TrackMemFree(buffer->size());
345 const bool is_client_side_array = IsUsageClientSideArray(usage); 347 const bool is_client_side_array = IsUsageClientSideArray(usage);
346 const bool support_fixed_attribs = 348 const bool support_fixed_attribs =
347 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; 349 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
350
348 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. 351 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002.
349 const bool shadow = target == GL_ELEMENT_ARRAY_BUFFER || 352 return (target == GL_ELEMENT_ARRAY_BUFFER ||
350 allow_buffers_on_multiple_targets_ || 353 allow_buffers_on_multiple_targets_ ||
351 (allow_fixed_attribs_ && !support_fixed_attribs) || 354 (allow_fixed_attribs_ && !support_fixed_attribs) ||
352 is_client_side_array; 355 is_client_side_array);
353 buffer->SetInfo(size, usage, shadow, data, is_client_side_array); 356 }
357
358 void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size,
359 GLenum usage, bool use_shadow) {
360 DCHECK(buffer);
361 memory_type_tracker_->TrackMemFree(buffer->size());
362 buffer->SetInfo(size, usage, use_shadow, IsUsageClientSideArray(usage));
354 memory_type_tracker_->TrackMemAlloc(buffer->size()); 363 memory_type_tracker_->TrackMemAlloc(buffer->size());
355 } 364 }
356 365
357 void BufferManager::ValidateAndDoBufferData( 366 void BufferManager::ValidateAndDoBufferData(
358 ContextState* context_state, GLenum target, GLsizeiptr size, 367 ContextState* context_state, GLenum target, GLsizeiptr size,
359 const GLvoid* data, GLenum usage) { 368 const GLvoid* data, GLenum usage) {
360 ErrorState* error_state = context_state->GetErrorState(); 369 ErrorState* error_state = context_state->GetErrorState();
361 if (!feature_info_->validators()->buffer_target.IsValid(target)) { 370 if (!feature_info_->validators()->buffer_target.IsValid(target)) {
362 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 371 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
363 error_state, "glBufferData", target, "target"); 372 error_state, "glBufferData", target, "target");
(...skipping 27 matching lines...) Expand all
391 } 400 }
392 401
393 402
394 void BufferManager::DoBufferData( 403 void BufferManager::DoBufferData(
395 ErrorState* error_state, 404 ErrorState* error_state,
396 Buffer* buffer, 405 Buffer* buffer,
397 GLenum target, 406 GLenum target,
398 GLsizeiptr size, 407 GLsizeiptr size,
399 GLenum usage, 408 GLenum usage,
400 const GLvoid* data) { 409 const GLvoid* data) {
401 // Clear the buffer to 0 if no initial data was passed in. 410
402 scoped_ptr<int8_t[]> zero; 411 // Stage the shadow buffer first if we are using a shadow buffer so that we
Ken Russell (switch to Gerrit) 2016/03/31 23:28:04 Is the indentation off here?
David Yen 2016/04/01 17:00:53 Done. I just ran cl format.
403 if (!data) { 412 // validate what we store internally.
404 zero.reset(new int8_t[size]); 413 const bool use_shadow = UseShadowBuffer(target, usage);
405 memset(zero.get(), 0, size); 414 data = buffer->StageShadow(use_shadow, size, data);
406 data = zero.get();
407 }
408 415
409 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); 416 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
410 if (IsUsageClientSideArray(usage)) { 417 if (IsUsageClientSideArray(usage)) {
411 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; 418 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0;
412 glBufferData(target, empty_size, NULL, usage); 419 glBufferData(target, empty_size, NULL, usage);
413 } else { 420 } else {
414 glBufferData(target, size, data, usage); 421 glBufferData(target, size, data, usage);
415 } 422 }
416 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); 423 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
417 if (error == GL_NO_ERROR) { 424 if (error != GL_NO_ERROR) {
418 SetInfo(buffer, target, size, usage, data); 425 size = 0;
419 } else { 426 buffer->StageShadow(false, 0, nullptr); // Also clear the shadow.
420 SetInfo(buffer, target, 0, usage, NULL);
421 } 427 }
428
429 SetInfo(buffer, target, size, usage, use_shadow);
422 } 430 }
423 431
424 void BufferManager::ValidateAndDoBufferSubData( 432 void BufferManager::ValidateAndDoBufferSubData(
425 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, 433 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size,
426 const GLvoid * data) { 434 const GLvoid * data) {
427 ErrorState* error_state = context_state->GetErrorState(); 435 ErrorState* error_state = context_state->GetErrorState();
428 Buffer* buffer = GetBufferInfoForTarget(context_state, target); 436 Buffer* buffer = GetBufferInfoForTarget(context_state, target);
429 if (!buffer) { 437 if (!buffer) {
430 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", 438 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData",
431 "unknown buffer"); 439 "unknown buffer");
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 auto guid = gfx::GetGLBufferGUIDForTracing( 632 auto guid = gfx::GetGLBufferGUIDForTracing(
625 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); 633 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id);
626 pmd->CreateSharedGlobalAllocatorDump(guid); 634 pmd->CreateSharedGlobalAllocatorDump(guid);
627 pmd->AddOwnershipEdge(dump->guid(), guid); 635 pmd->AddOwnershipEdge(dump->guid(), guid);
628 } 636 }
629 return true; 637 return true;
630 } 638 }
631 639
632 } // namespace gles2 640 } // namespace gles2
633 } // namespace gpu 641 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/buffer_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698