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

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: shadow->use_shadow, Format, vector Clear+Insert/Resize 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
141 void Buffer::SetInfo( 140 const GLvoid* Buffer::StageShadow(bool use_shadow,
142 GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, 141 GLsizeiptr size,
143 bool is_client_side_array) { 142 const GLvoid* data) {
143 shadow_.clear();
144 if (use_shadow) {
145 if (data) {
146 shadow_.insert(shadow_.begin(),
147 static_cast<const uint8_t*>(data),
148 static_cast<const uint8_t*>(data) + size);
149 } else {
150 shadow_.resize(size);
151 }
152 return shadow_.data();
153 } else {
154 return data;
155 }
156 }
157
158 void Buffer::SetInfo(GLsizeiptr size,
159 GLenum usage,
160 bool use_shadow,
161 bool is_client_side_array) {
144 usage_ = usage; 162 usage_ = usage;
145 is_client_side_array_ = is_client_side_array; 163 is_client_side_array_ = is_client_side_array;
146 ClearCache(); 164 ClearCache();
147 if (size != size_ || shadow != shadowed_) { 165
148 shadowed_ = shadow; 166 // Shadow must have been setup already.
149 size_ = size; 167 DCHECK_EQ(shadow_.size(), static_cast<size_t>(use_shadow ? size : 0u));
150 if (shadowed_) { 168 size_ = size;
151 shadow_.reset(new int8_t[size]); 169
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); 170 mapped_range_.reset(nullptr);
164 } 171 }
165 172
166 bool Buffer::CheckRange( 173 bool Buffer::CheckRange(
167 GLintptr offset, GLsizeiptr size) const { 174 GLintptr offset, GLsizeiptr size) const {
168 int32_t end = 0; 175 int32_t end = 0;
169 return offset >= 0 && size >= 0 && 176 return offset >= 0 && size >= 0 &&
170 offset <= std::numeric_limits<int32_t>::max() && 177 offset <= std::numeric_limits<int32_t>::max() &&
171 size <= std::numeric_limits<int32_t>::max() && 178 size <= std::numeric_limits<int32_t>::max() &&
172 SafeAddInt32(offset, size, &end) && end <= size_; 179 SafeAddInt32(offset, size, &end) && end <= size_;
173 } 180 }
174 181
175 bool Buffer::SetRange( 182 bool Buffer::SetRange(
176 GLintptr offset, GLsizeiptr size, const GLvoid * data) { 183 GLintptr offset, GLsizeiptr size, const GLvoid * data) {
177 if (!CheckRange(offset, size)) { 184 if (!CheckRange(offset, size)) {
178 return false; 185 return false;
179 } 186 }
180 if (shadowed_) { 187 if (!shadow_.empty()) {
181 memcpy(shadow_.get() + offset, data, size); 188 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
189 memcpy(shadow_.data() + offset, data, size);
182 ClearCache(); 190 ClearCache();
183 } 191 }
184 return true; 192 return true;
185 } 193 }
186 194
187 const void* Buffer::GetRange( 195 const void* Buffer::GetRange(
188 GLintptr offset, GLsizeiptr size) const { 196 GLintptr offset, GLsizeiptr size) const {
189 if (!shadowed_) { 197 if (shadow_.empty()) {
190 return NULL; 198 return NULL;
191 } 199 }
192 if (!CheckRange(offset, size)) { 200 if (!CheckRange(offset, size)) {
193 return NULL; 201 return NULL;
194 } 202 }
195 return shadow_.get() + offset; 203 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
204 return shadow_.data() + offset;
196 } 205 }
197 206
198 void Buffer::ClearCache() { 207 void Buffer::ClearCache() {
199 range_set_.clear(); 208 range_set_.clear();
200 } 209 }
201 210
202 template <typename T> 211 template <typename T>
203 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, 212 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count,
204 GLuint primitive_restart_index) { 213 GLuint primitive_restart_index) {
205 GLuint max_value = 0; 214 GLuint max_value = 0;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 } 282 }
274 283
275 if (!SafeAddUint32(offset, size, &size)) { 284 if (!SafeAddUint32(offset, size, &size)) {
276 return false; 285 return false;
277 } 286 }
278 287
279 if (size > static_cast<uint32_t>(size_)) { 288 if (size > static_cast<uint32_t>(size_)) {
280 return false; 289 return false;
281 } 290 }
282 291
283 if (!shadowed_) { 292 if (shadow_.empty()) {
284 return false; 293 return false;
285 } 294 }
286 295
287 // Scan the range for the max value and store 296 // Scan the range for the max value and store
288 GLuint max_v = 0; 297 GLuint max_v = 0;
289 switch (type) { 298 switch (type) {
290 case GL_UNSIGNED_BYTE: 299 case GL_UNSIGNED_BYTE:
291 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count, 300 max_v = GetMaxValue<uint8_t>(shadow_.data(), offset, count,
292 primitive_restart_index); 301 primitive_restart_index);
293 break; 302 break;
294 case GL_UNSIGNED_SHORT: 303 case GL_UNSIGNED_SHORT:
295 // Check we are not accessing an odd byte for a 2 byte value. 304 // Check we are not accessing an odd byte for a 2 byte value.
296 if ((offset & 1) != 0) { 305 if ((offset & 1) != 0) {
297 return false; 306 return false;
298 } 307 }
299 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count, 308 max_v = GetMaxValue<uint16_t>(shadow_.data(), offset, count,
300 primitive_restart_index); 309 primitive_restart_index);
301 break; 310 break;
302 case GL_UNSIGNED_INT: 311 case GL_UNSIGNED_INT:
303 // Check we are not accessing a non aligned address for a 4 byte value. 312 // Check we are not accessing a non aligned address for a 4 byte value.
304 if ((offset & 3) != 0) { 313 if ((offset & 3) != 0) {
305 return false; 314 return false;
306 } 315 }
307 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count, 316 max_v = GetMaxValue<uint32_t>(shadow_.data(), offset, count,
308 primitive_restart_index); 317 primitive_restart_index);
309 break; 318 break;
310 default: 319 default:
311 NOTREACHED(); // should never get here by validation. 320 NOTREACHED(); // should never get here by validation.
312 break; 321 break;
313 } 322 }
314 range_set_.insert(std::make_pair(range, max_v)); 323 range_set_.insert(std::make_pair(range, max_v));
315 *max_value = max_v; 324 *max_value = max_v;
316 return true; 325 return true;
317 } 326 }
318 327
(...skipping 12 matching lines...) Expand all
331 bool BufferManager::IsUsageClientSideArray(GLenum usage) { 340 bool BufferManager::IsUsageClientSideArray(GLenum usage) {
332 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; 341 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_;
333 } 342 }
334 343
335 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { 344 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() {
336 return feature_info_.get() && 345 return feature_info_.get() &&
337 feature_info_->workarounds() 346 feature_info_->workarounds()
338 .use_non_zero_size_for_client_side_stream_buffers; 347 .use_non_zero_size_for_client_side_stream_buffers;
339 } 348 }
340 349
341 void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, 350 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); 351 const bool is_client_side_array = IsUsageClientSideArray(usage);
346 const bool support_fixed_attribs = 352 const bool support_fixed_attribs =
347 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; 353 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
354
348 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. 355 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002.
349 const bool shadow = target == GL_ELEMENT_ARRAY_BUFFER || 356 return (
350 allow_buffers_on_multiple_targets_ || 357 target == GL_ELEMENT_ARRAY_BUFFER || allow_buffers_on_multiple_targets_ ||
351 (allow_fixed_attribs_ && !support_fixed_attribs) || 358 (allow_fixed_attribs_ && !support_fixed_attribs) || is_client_side_array);
352 is_client_side_array; 359 }
353 buffer->SetInfo(size, usage, shadow, data, is_client_side_array); 360
361 void BufferManager::SetInfo(Buffer* buffer,
362 GLenum target,
363 GLsizeiptr size,
364 GLenum usage,
365 bool use_shadow) {
366 DCHECK(buffer);
367 memory_type_tracker_->TrackMemFree(buffer->size());
368 buffer->SetInfo(size, usage, use_shadow, IsUsageClientSideArray(usage));
354 memory_type_tracker_->TrackMemAlloc(buffer->size()); 369 memory_type_tracker_->TrackMemAlloc(buffer->size());
355 } 370 }
356 371
357 void BufferManager::ValidateAndDoBufferData( 372 void BufferManager::ValidateAndDoBufferData(
358 ContextState* context_state, GLenum target, GLsizeiptr size, 373 ContextState* context_state, GLenum target, GLsizeiptr size,
359 const GLvoid* data, GLenum usage) { 374 const GLvoid* data, GLenum usage) {
360 ErrorState* error_state = context_state->GetErrorState(); 375 ErrorState* error_state = context_state->GetErrorState();
361 if (!feature_info_->validators()->buffer_target.IsValid(target)) { 376 if (!feature_info_->validators()->buffer_target.IsValid(target)) {
362 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 377 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
363 error_state, "glBufferData", target, "target"); 378 error_state, "glBufferData", target, "target");
(...skipping 27 matching lines...) Expand all
391 } 406 }
392 407
393 408
394 void BufferManager::DoBufferData( 409 void BufferManager::DoBufferData(
395 ErrorState* error_state, 410 ErrorState* error_state,
396 Buffer* buffer, 411 Buffer* buffer,
397 GLenum target, 412 GLenum target,
398 GLsizeiptr size, 413 GLsizeiptr size,
399 GLenum usage, 414 GLenum usage,
400 const GLvoid* data) { 415 const GLvoid* data) {
401 // Clear the buffer to 0 if no initial data was passed in. 416 // Stage the shadow buffer first if we are using a shadow buffer so that we
402 scoped_ptr<int8_t[]> zero; 417 // validate what we store internally.
403 if (!data) { 418 const bool use_shadow = UseShadowBuffer(target, usage);
404 zero.reset(new int8_t[size]); 419 data = buffer->StageShadow(use_shadow, size, data);
405 memset(zero.get(), 0, size);
406 data = zero.get();
407 }
408 420
409 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); 421 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
410 if (IsUsageClientSideArray(usage)) { 422 if (IsUsageClientSideArray(usage)) {
411 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; 423 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0;
412 glBufferData(target, empty_size, NULL, usage); 424 glBufferData(target, empty_size, NULL, usage);
413 } else { 425 } else {
414 glBufferData(target, size, data, usage); 426 glBufferData(target, size, data, usage);
415 } 427 }
416 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); 428 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
417 if (error == GL_NO_ERROR) { 429 if (error != GL_NO_ERROR) {
418 SetInfo(buffer, target, size, usage, data); 430 size = 0;
419 } else { 431 buffer->StageShadow(false, 0, nullptr); // Also clear the shadow.
420 SetInfo(buffer, target, 0, usage, NULL);
421 } 432 }
433
434 SetInfo(buffer, target, size, usage, use_shadow);
422 } 435 }
423 436
424 void BufferManager::ValidateAndDoBufferSubData( 437 void BufferManager::ValidateAndDoBufferSubData(
425 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, 438 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size,
426 const GLvoid * data) { 439 const GLvoid * data) {
427 ErrorState* error_state = context_state->GetErrorState(); 440 ErrorState* error_state = context_state->GetErrorState();
428 Buffer* buffer = GetBufferInfoForTarget(context_state, target); 441 Buffer* buffer = GetBufferInfoForTarget(context_state, target);
429 if (!buffer) { 442 if (!buffer) {
430 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", 443 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData",
431 "unknown buffer"); 444 "unknown buffer");
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 auto guid = gfx::GetGLBufferGUIDForTracing( 637 auto guid = gfx::GetGLBufferGUIDForTracing(
625 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); 638 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id);
626 pmd->CreateSharedGlobalAllocatorDump(guid); 639 pmd->CreateSharedGlobalAllocatorDump(guid);
627 pmd->AddOwnershipEdge(dump->guid(), guid); 640 pmd->AddOwnershipEdge(dump->guid(), guid);
628 } 641 }
629 return true; 642 return true;
630 } 643 }
631 644
632 } // namespace gles2 645 } // namespace gles2
633 } // namespace gpu 646 } // 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