On 14 December 2012 13:01, Paul Berry <span dir="ltr"><<a href="mailto:stereotype441@gmail.com" target="_blank">stereotype441@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>From the GL 4.3 spec, section 6.7.1 (Indexed Buffer Object Limits and<br>
Binding Queries):<br>
<br>
To query the starting offset or size of the range of a buffer<br>
object binding in an indexed array, call GetInteger64i v with<br>
target set to respectively the starting offset or binding size<br>
name from table 6.5 for that array. index must be in the range<br>
zero to the number of bind points supported minus one. If the<br>
starting offset or size was not specified when the buffer object<br>
was bound (e.g. if it was bound with BindBufferBase), or if no<br>
buffer object is bound to the target array at index, zero is<br>
returned.<br>
<br>
Similar language exists in the EXT_transform_feedback spec and in the<br>
GLES3 spec.<br>
<br>
Previously, if a buffer object was bound by glBindBufferBase(), the<br>
GL_TRANSFORM_FEEDBACK_BUFFER_SIZE query returned the size of the<br>
buffer.<br>
<br>
Fixes GLES3 conformance tests<br>
transform_feedback_{builtin_type,state_variables}.test.<br></blockquote><div><br>NAK this patch. After some more careful re-reading of the GL and GLES specs, I believe it implements the wrong behaviour. I'm thinking in particular of this text (the last two paragraphs of section 2.9.1 of the GLES 3 spec):<br>
<br>"BindBufferBase binds the entire buffer, even when the size of the buffer is changed after the binding is established. It is equivalent to calling BindBufferRange with offset zero, while size is determined by the size of the bound buffer at the time the binding is used.<br>
<br>"Regardless of the size specified with BindBufferRange, or indirectly with BindBufferBase, the GL will never read or write beyond the end of a bound buffer. In some cases this constraint may result in visibly different behavior when a buffer overflow would otherwise result, such as described for transform feedback operations in section 2.14.2."<br>
<br>In the context of transform feedback, I interpret the phrase "at the time the binding is used" to mean "at the time BeginTransformFeedback is called." Mesa's current behaviour isn't consistent with the above two paragraphs: it records the size of the buffer at the time BindBufferBase is called, which means that if the buffer is grown after it's bound (but before it's used), the entire buffer won't be used. Worse yet, in the absence of extra checking by the driver, if the buffer is shrunk after it's bound, there's a danger of transform feedback results overflowing past the end of the buffer.<br>
<br>I'm working on a replacement patch.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
---<br>
src/mesa/main/get.c | 2 +-<br>
src/mesa/main/mtypes.h | 7 +++++++<br>
src/mesa/main/transformfeedback.c | 10 ++++++----<br>
3 files changed, 14 insertions(+), 5 deletions(-)<br>
<br>
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c<br>
index f3dbda2..2348486 100644<br>
--- a/src/mesa/main/get.c<br>
+++ b/src/mesa/main/get.c<br>
@@ -1574,7 +1574,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)<br>
goto invalid_value;<br>
if (!ctx->Extensions.EXT_transform_feedback)<br>
goto invalid_enum;<br>
- v->value_int64 = ctx->TransformFeedback.CurrentObject->Size[index];<br>
+ v->value_int64 = ctx->TransformFeedback.CurrentObject->QuerySize[index];<br>
return TYPE_INT64;<br>
<br>
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:<br>
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h<br>
index 18ab2db..333b2c9 100644<br>
--- a/src/mesa/main/mtypes.h<br>
+++ b/src/mesa/main/mtypes.h<br>
@@ -1827,6 +1827,13 @@ struct gl_transform_feedback_object<br>
GLintptr Offset[MAX_FEEDBACK_BUFFERS];<br>
/** Max data to put into dest buffer (in bytes) */<br>
GLsizeiptr Size[MAX_FEEDBACK_BUFFERS];<br>
+ /**<br>
+ * Size that should be returned from GL_TRANSFORM_FEEDBACK_BUFFER_SIZE<br>
+ * queries. If the transform feedback buffer was set up with<br>
+ * glBindBufferBase() or glBindBufferOffsetEXT(). If it was set up with<br>
+ * glBindBufferRange() it is equal to ActualSize.<br>
+ */<br>
+ GLsizeiptr QuerySize[MAX_FEEDBACK_BUFFERS];<br>
};<br>
<br>
<br>
diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c<br>
index 7d500bc..092c343 100644<br>
--- a/src/mesa/main/transformfeedback.c<br>
+++ b/src/mesa/main/transformfeedback.c<br>
@@ -383,7 +383,8 @@ _mesa_EndTransformFeedback(void)<br>
static void<br>
bind_buffer_range(struct gl_context *ctx, GLuint index,<br>
struct gl_buffer_object *bufObj,<br>
- GLintptr offset, GLsizeiptr size)<br>
+ GLintptr offset, GLsizeiptr size,<br>
+ GLsizeiptr query_size)<br>
{<br>
struct gl_transform_feedback_object *obj =<br>
ctx->TransformFeedback.CurrentObject;<br>
@@ -407,6 +408,7 @@ bind_buffer_range(struct gl_context *ctx, GLuint index,<br>
<br>
obj->Offset[index] = offset;<br>
obj->Size[index] = size;<br>
+ obj->QuerySize[index] = query_size;<br>
}<br>
<br>
<br>
@@ -450,7 +452,7 @@ _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,<br>
return;<br>
}<br>
<br>
- bind_buffer_range(ctx, index, bufObj, offset, size);<br>
+ bind_buffer_range(ctx, index, bufObj, offset, size, size);<br>
}<br>
<br>
<br>
@@ -485,7 +487,7 @@ _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,<br>
*/<br>
size = bufObj->Size & ~0x3;<br>
<br>
- bind_buffer_range(ctx, index, bufObj, 0, size);<br>
+ bind_buffer_range(ctx, index, bufObj, 0, size, 0);<br>
}<br>
<br>
<br>
@@ -546,7 +548,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,<br>
*/<br>
size = (bufObj->Size - offset) & ~0x3;<br>
<br>
- bind_buffer_range(ctx, index, bufObj, offset, size);<br>
+ bind_buffer_range(ctx, index, bufObj, offset, size, 0);<br>
}<br>
<span class=""><font color="#888888"><br>
<br>
--<br>
1.8.0.2<br>
<br>
</font></span></blockquote></div><br></div>