X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fintel%2Fintel_buffer_objects.c;h=3b7015b5ad39a7842277046c48be24163ee0b5cd;hb=539a14a1dd5a0d277b193d9cd2d06423ed98dc8a;hp=3cf0ea0991d3b12de970577dd060c1324ac5604b;hpb=9053bb0d405db0b1a2a917317c7ec41e63b54f09;p=mesa.git diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index 3cf0ea0991d..3b7015b5ad3 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c @@ -130,9 +130,10 @@ intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj) * Allocate space for and store data in a buffer object. Any data that was * previously stored in the buffer object is lost. If data is NULL, * memory will be allocated, but no copy will occur. - * Called via glBufferDataARB(). + * Called via ctx->Driver.BufferData(). + * \return GL_TRUE for success, GL_FALSE if out of memory */ -static void +static GLboolean intel_bufferobj_data(GLcontext * ctx, GLenum target, GLsizeiptrARB size, @@ -167,15 +168,19 @@ intel_bufferobj_data(GLcontext * ctx, if (intel_obj->sys_buffer != NULL) { if (data != NULL) memcpy(intel_obj->sys_buffer, data, size); - return; + return GL_TRUE; } } #endif intel_bufferobj_alloc_buffer(intel, intel_obj); + if (!intel_obj->buffer) + return GL_FALSE; if (data != NULL) dri_bo_subdata(intel_obj->buffer, 0, size, data); } + + return GL_TRUE; } @@ -202,8 +207,26 @@ intel_bufferobj_subdata(GLcontext * ctx, if (intel_obj->sys_buffer) memcpy((char *)intel_obj->sys_buffer + offset, data, size); - else - dri_bo_subdata(intel_obj->buffer, offset, size, data); + else { + /* Flush any existing batchbuffer that might reference this data. */ + if (drm_intel_bo_busy(intel_obj->buffer) || + drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) { + drm_intel_bo *temp_bo; + + temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64); + + drm_intel_bo_subdata(temp_bo, 0, size, data); + + intel_emit_linear_blit(intel, + intel_obj->buffer, offset, + temp_bo, 0, + size); + + drm_intel_bo_unreference(temp_bo); + } else { + dri_bo_subdata(intel_obj->buffer, offset, size, data); + } + } } @@ -220,7 +243,10 @@ intel_bufferobj_get_subdata(GLcontext * ctx, struct intel_buffer_object *intel_obj = intel_buffer_object(obj); assert(intel_obj); - dri_bo_get_subdata(intel_obj->buffer, offset, size, data); + if (intel_obj->sys_buffer) + memcpy(data, (char *)intel_obj->sys_buffer + offset, size); + else + dri_bo_get_subdata(intel_obj->buffer, offset, size, data); } @@ -242,13 +268,14 @@ intel_bufferobj_map(GLcontext * ctx, if (intel_obj->sys_buffer) { obj->Pointer = intel_obj->sys_buffer; + obj->Length = obj->Size; + obj->Offset = 0; return obj->Pointer; } - /* Flush any existing batchbuffer that might have written to this - * buffer. - */ - intelFlush(ctx); + /* Flush any existing batchbuffer that might reference this data. */ + if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) + intelFlush(ctx); if (intel_obj->region) intel_bufferobj_cow(intel, intel_obj); @@ -267,6 +294,9 @@ intel_bufferobj_map(GLcontext * ctx, } obj->Pointer = intel_obj->buffer->virtual; + obj->Length = obj->Size; + obj->Offset = 0; + return obj->Pointer; } @@ -288,7 +318,7 @@ intel_bufferobj_map(GLcontext * ctx, */ static void * intel_bufferobj_map_range(GLcontext * ctx, - GLenum target, GLsizei offset, GLsizeiptr length, + GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, struct gl_buffer_object *obj) { struct intel_context *intel = intel_context(ctx); @@ -296,6 +326,13 @@ intel_bufferobj_map_range(GLcontext * ctx, assert(intel_obj); + /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also + * internally uses our functions directly. + */ + obj->Offset = offset; + obj->Length = length; + obj->AccessFlags = access; + if (intel_obj->sys_buffer) { obj->Pointer = intel_obj->sys_buffer + offset; return obj->Pointer; @@ -308,16 +345,10 @@ intel_bufferobj_map_range(GLcontext * ctx, * the batchbuffer so that GEM knows about the buffer access for later * syncing. */ - if ((access & GL_MAP_WRITE_BIT) && !(access & GL_MAP_UNSYNCHRONIZED_BIT)) + if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) && + drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) intelFlush(ctx); - /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also - * internally uses our functions directly. - */ - obj->Offset = offset; - obj->Length = length; - obj->AccessFlags = access; - if (intel_obj->buffer == NULL) { obj->Pointer = NULL; return NULL; @@ -341,19 +372,24 @@ intel_bufferobj_map_range(GLcontext * ctx, */ if ((access & GL_MAP_INVALIDATE_RANGE_BIT) && drm_intel_bo_busy(intel_obj->buffer)) { - intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr, - "range map", - length, 64); - if (!(access & GL_MAP_READ_BIT) && - intel->intelScreen->kernel_exec_fencing) { - drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo); - intel_obj->mapped_gtt = GL_TRUE; + if (access & GL_MAP_FLUSH_EXPLICIT_BIT) { + intel_obj->range_map_buffer = _mesa_malloc(length); + obj->Pointer = intel_obj->range_map_buffer; } else { - drm_intel_bo_map(intel_obj->range_map_bo, - (access & GL_MAP_WRITE_BIT) != 0); - intel_obj->mapped_gtt = GL_FALSE; + intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr, + "range map", + length, 64); + if (!(access & GL_MAP_READ_BIT) && + intel->intelScreen->kernel_exec_fencing) { + drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo); + intel_obj->mapped_gtt = GL_TRUE; + } else { + drm_intel_bo_map(intel_obj->range_map_bo, + (access & GL_MAP_WRITE_BIT) != 0); + intel_obj->mapped_gtt = GL_FALSE; + } + obj->Pointer = intel_obj->range_map_bo->virtual; } - obj->Pointer = intel_obj->range_map_bo->virtual; return obj->Pointer; } @@ -370,6 +406,38 @@ intel_bufferobj_map_range(GLcontext * ctx, return obj->Pointer; } +/* Ideally we'd use a BO to avoid taking up cache space for the temporary + * data, but FlushMappedBufferRange may be followed by further writes to + * the pointer, so we would have to re-map after emitting our blit, which + * would defeat the point. + */ +static void +intel_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target, + GLintptr offset, GLsizeiptr length, + struct gl_buffer_object *obj) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_buffer_object *intel_obj = intel_buffer_object(obj); + drm_intel_bo *temp_bo; + + /* Unless we're in the range map using a temporary system buffer, + * there's no work to do. + */ + if (intel_obj->range_map_buffer == NULL) + return; + + temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64); + + drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer); + + intel_emit_linear_blit(intel, + intel_obj->buffer, obj->Offset + offset, + temp_bo, 0, + length); + + drm_intel_bo_unreference(temp_bo); +} + /** * Called via glUnmapBuffer(). @@ -385,6 +453,15 @@ intel_bufferobj_unmap(GLcontext * ctx, assert(obj->Pointer); if (intel_obj->sys_buffer != NULL) { /* always keep the mapping around. */ + } else if (intel_obj->range_map_buffer != NULL) { + /* Since we've emitted some blits to buffers that will (likely) be used + * in rendering operations in other cache domains in this batch, emit a + * flush. Once again, we wish for a domain tracker in libdrm to cover + * usage inside of a batchbuffer. + */ + intel_batchbuffer_emit_mi_flush(intel->batch); + free(intel_obj->range_map_buffer); + intel_obj->range_map_buffer = NULL; } else if (intel_obj->range_map_bo != NULL) { if (intel_obj->mapped_gtt) { drm_intel_gem_bo_unmap_gtt(intel_obj->range_map_bo); @@ -392,10 +469,6 @@ intel_bufferobj_unmap(GLcontext * ctx, drm_intel_bo_unmap(intel_obj->range_map_bo); } - /* We ignore the FLUSH_EXPLICIT bit and the calls associated with it. - * It would be a small win to support that, but for now we just copy - * the whole mapped range into place. - */ intel_emit_linear_blit(intel, intel_obj->buffer, obj->Offset, intel_obj->range_map_bo, 0, @@ -418,6 +491,8 @@ intel_bufferobj_unmap(GLcontext * ctx, } } obj->Pointer = NULL; + obj->Offset = 0; + obj->Length = 0; return GL_TRUE; } @@ -523,6 +598,7 @@ intelInitBufferObjectFuncs(struct dd_function_table *functions) functions->GetBufferSubData = intel_bufferobj_get_subdata; functions->MapBuffer = intel_bufferobj_map; functions->MapBufferRange = intel_bufferobj_map_range; + functions->FlushMappedBufferRange = intel_bufferobj_flush_mapped_range; functions->UnmapBuffer = intel_bufferobj_unmap; functions->CopyBufferSubData = intel_bufferobj_copy_subdata; }