瀏覽代碼

libobs: Add vertex/index buffer "direct" flush functions

(Note: This commit also modifies libobs-d3d11 and libobs-opengl)

Allows the ability to flush data directly without having to use the
buffer's internal data.

Allows the caller to manage his/her own vertex/index buffer data if
desired, working around the design flaw of having to rely on a
vertex/index buffer's internal data.
jp9000 8 年之前
父節點
當前提交
c111fa68b8

+ 42 - 14
libobs-d3d11/d3d11-subsystem.cpp

@@ -1938,36 +1938,53 @@ void gs_vertexbuffer_destroy(gs_vertbuffer_t *vertbuffer)
 	delete vertbuffer;
 }
 
-void gs_vertexbuffer_flush(gs_vertbuffer_t *vertbuffer)
+static inline void gs_vertexbuffer_flush_internal(gs_vertbuffer_t *vertbuffer,
+		const gs_vb_data *data)
 {
+	size_t num_tex = data->num_tex < vertbuffer->uvBuffers.size()
+		? data->num_tex
+		: vertbuffer->uvBuffers.size();
+
 	if (!vertbuffer->dynamic) {
 		blog(LOG_ERROR, "gs_vertexbuffer_flush: vertex buffer is "
 		                "not dynamic");
 		return;
 	}
 
-	vertbuffer->FlushBuffer(vertbuffer->vertexBuffer,
-			vertbuffer->vbd.data->points, sizeof(vec3));
+	if (data->points)
+		vertbuffer->FlushBuffer(vertbuffer->vertexBuffer,
+				data->points, sizeof(vec3));
 
-	if (vertbuffer->normalBuffer)
+	if (vertbuffer->normalBuffer && data->normals)
 		vertbuffer->FlushBuffer(vertbuffer->normalBuffer,
-				vertbuffer->vbd.data->normals, sizeof(vec3));
+				data->normals, sizeof(vec3));
 
-	if (vertbuffer->tangentBuffer)
+	if (vertbuffer->tangentBuffer && data->tangents)
 		vertbuffer->FlushBuffer(vertbuffer->tangentBuffer,
-				vertbuffer->vbd.data->tangents, sizeof(vec3));
+				data->tangents, sizeof(vec3));
 
-	if (vertbuffer->colorBuffer)
+	if (vertbuffer->colorBuffer && data->colors)
 		vertbuffer->FlushBuffer(vertbuffer->colorBuffer,
-				vertbuffer->vbd.data->colors, sizeof(uint32_t));
+				data->colors, sizeof(uint32_t));
 
-	for (size_t i = 0; i < vertbuffer->uvBuffers.size(); i++) {
-		gs_tvertarray &tv = vertbuffer->vbd.data->tvarray[i];
+	for (size_t i = 0; i < num_tex; i++) {
+		gs_tvertarray &tv = data->tvarray[i];
 		vertbuffer->FlushBuffer(vertbuffer->uvBuffers[i],
 				tv.array, tv.width*sizeof(float));
 	}
 }
 
+void gs_vertexbuffer_flush(gs_vertbuffer_t *vertbuffer)
+{
+	gs_vertexbuffer_flush_internal(vertbuffer, vertbuffer->vbd.data);
+}
+
+void gs_vertexbuffer_flush_direct(gs_vertbuffer_t *vertbuffer,
+		const gs_vb_data *data)
+{
+	gs_vertexbuffer_flush_internal(vertbuffer, data);
+}
+
 struct gs_vb_data *gs_vertexbuffer_get_data(const gs_vertbuffer_t *vertbuffer)
 {
 	return vertbuffer->vbd.data;
@@ -1979,7 +1996,8 @@ void gs_indexbuffer_destroy(gs_indexbuffer_t *indexbuffer)
 	delete indexbuffer;
 }
 
-void gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer)
+static inline void gs_indexbuffer_flush_internal(gs_indexbuffer_t *indexbuffer,
+		const void *data)
 {
 	HRESULT hr;
 
@@ -1992,12 +2010,22 @@ void gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer)
 	if (FAILED(hr))
 		return;
 
-	memcpy(map.pData, indexbuffer->indices.data,
-			indexbuffer->num * indexbuffer->indexSize);
+	memcpy(map.pData, data, indexbuffer->num * indexbuffer->indexSize);
 
 	indexbuffer->device->context->Unmap(indexbuffer->indexBuffer, 0);
 }
 
+void gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer)
+{
+	gs_indexbuffer_flush_internal(indexbuffer, indexbuffer->indices.data);
+}
+
+void gs_indexbuffer_flush_direct(gs_indexbuffer_t *indexbuffer,
+		const void *data)
+{
+	gs_indexbuffer_flush_internal(indexbuffer, data);
+}
+
 void *gs_indexbuffer_get_data(const gs_indexbuffer_t *indexbuffer)
 {
 	return indexbuffer->indices.data;

+ 13 - 3
libobs-opengl/gl-indexbuffer.c

@@ -70,15 +70,15 @@ void gs_indexbuffer_destroy(gs_indexbuffer_t *ib)
 	}
 }
 
-void gs_indexbuffer_flush(gs_indexbuffer_t *ib)
+static inline void gs_indexbuffer_flush_internal(gs_indexbuffer_t *ib,
+		const void *data)
 {
 	if (!ib->dynamic) {
 		blog(LOG_ERROR, "Index buffer is not dynamic");
 		goto fail;
 	}
 
-	if (!update_buffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer, ib->data,
-				ib->size))
+	if (!update_buffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer, data, ib->size))
 		goto fail;
 
 	return;
@@ -87,6 +87,16 @@ fail:
 	blog(LOG_ERROR, "gs_indexbuffer_flush (GL) failed");
 }
 
+void gs_indexbuffer_flush(gs_indexbuffer_t *ib)
+{
+	gs_indexbuffer_flush_internal(ib, ib->data);
+}
+
+void gs_indexbuffer_flush_direct(gs_indexbuffer_t *ib, const void *data)
+{
+	gs_indexbuffer_flush_internal(ib, data);
+}
+
 void *gs_indexbuffer_get_data(const gs_indexbuffer_t *ib)
 {
 	return ib->data;

+ 34 - 17
libobs-opengl/gl-vertexbuffer.c

@@ -120,45 +120,51 @@ void gs_vertexbuffer_destroy(gs_vertbuffer_t *vb)
 	}
 }
 
-void gs_vertexbuffer_flush(gs_vertbuffer_t *vb)
+static inline void gs_vertexbuffer_flush_internal(gs_vertbuffer_t *vb,
+		const struct gs_vb_data *data)
 {
 	size_t i;
+	size_t num_tex = data->num_tex < vb->data->num_tex
+		? data->num_tex
+		: vb->data->num_tex;
 
 	if (!vb->dynamic) {
 		blog(LOG_ERROR, "vertex buffer is not dynamic");
 		goto failed;
 	}
 
-	if (!update_buffer(GL_ARRAY_BUFFER, vb->vertex_buffer,
-				vb->data->points,
-				vb->data->num * sizeof(struct vec3)))
-		goto failed;
+	if (data->points) {
+		if (!update_buffer(GL_ARRAY_BUFFER, vb->vertex_buffer,
+					data->points,
+					data->num * sizeof(struct vec3)))
+			goto failed;
+	}
 
-	if (vb->normal_buffer) {
+	if (vb->normal_buffer && data->normals) {
 		if (!update_buffer(GL_ARRAY_BUFFER, vb->normal_buffer,
-					vb->data->normals,
-					vb->data->num * sizeof(struct vec3)))
+					data->normals,
+					data->num * sizeof(struct vec3)))
 			goto failed;
 	}
 
-	if (vb->tangent_buffer) {
+	if (vb->tangent_buffer && data->tangents) {
 		if (!update_buffer(GL_ARRAY_BUFFER, vb->tangent_buffer,
-					vb->data->tangents,
-					vb->data->num * sizeof(struct vec3)))
+					data->tangents,
+					data->num * sizeof(struct vec3)))
 			goto failed;
 	}
 
-	if (vb->color_buffer) {
+	if (vb->color_buffer && data->colors) {
 		if (!update_buffer(GL_ARRAY_BUFFER, vb->color_buffer,
-					vb->data->colors,
-					vb->data->num * sizeof(uint32_t)))
+					data->colors,
+					data->num * sizeof(uint32_t)))
 			goto failed;
 	}
 
-	for (i = 0; i < vb->data->num_tex; i++) {
+	for (i = 0; i < num_tex; i++) {
 		GLuint buffer = vb->uv_buffers.array[i];
-		struct gs_tvertarray *tv = vb->data->tvarray+i;
-		size_t size = vb->data->num * tv->width * sizeof(float);
+		struct gs_tvertarray *tv = data->tvarray+i;
+		size_t size = data->num * tv->width * sizeof(float);
 
 		if (!update_buffer(GL_ARRAY_BUFFER, buffer, tv->array, size))
 			goto failed;
@@ -170,6 +176,17 @@ failed:
 	blog(LOG_ERROR, "gs_vertexbuffer_flush (GL) failed");
 }
 
+void gs_vertexbuffer_flush(gs_vertbuffer_t *vb)
+{
+	gs_vertexbuffer_flush_internal(vb, vb->data);
+}
+
+void gs_vertexbuffer_flush_direct(gs_vertbuffer_t *vb,
+		const struct gs_vb_data *data)
+{
+	gs_vertexbuffer_flush_internal(vb, data);
+}
+
 struct gs_vb_data *gs_vertexbuffer_get_data(const gs_vertbuffer_t *vb)
 {
 	return vb->data;

+ 2 - 0
libobs/graphics/graphics-imports.c

@@ -141,10 +141,12 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
 
 	GRAPHICS_IMPORT(gs_vertexbuffer_destroy);
 	GRAPHICS_IMPORT(gs_vertexbuffer_flush);
+	GRAPHICS_IMPORT(gs_vertexbuffer_flush_direct);
 	GRAPHICS_IMPORT(gs_vertexbuffer_get_data);
 
 	GRAPHICS_IMPORT(gs_indexbuffer_destroy);
 	GRAPHICS_IMPORT(gs_indexbuffer_flush);
+	GRAPHICS_IMPORT(gs_indexbuffer_flush_direct);
 	GRAPHICS_IMPORT(gs_indexbuffer_get_data);
 	GRAPHICS_IMPORT(gs_indexbuffer_get_num_indices);
 	GRAPHICS_IMPORT(gs_indexbuffer_get_type);

+ 4 - 0
libobs/graphics/graphics-internal.h

@@ -189,11 +189,15 @@ struct gs_exports {
 
 	void (*gs_vertexbuffer_destroy)(gs_vertbuffer_t *vertbuffer);
 	void (*gs_vertexbuffer_flush)(gs_vertbuffer_t *vertbuffer);
+	void (*gs_vertexbuffer_flush_direct)(gs_vertbuffer_t *vertbuffer,
+			const struct gs_vb_data *data);
 	struct gs_vb_data *(*gs_vertexbuffer_get_data)(
 			const gs_vertbuffer_t *vertbuffer);
 
 	void   (*gs_indexbuffer_destroy)(gs_indexbuffer_t *indexbuffer);
 	void   (*gs_indexbuffer_flush)(gs_indexbuffer_t *indexbuffer);
+	void   (*gs_indexbuffer_flush_direct)(gs_indexbuffer_t *indexbuffer,
+			const void *data);
 	void  *(*gs_indexbuffer_get_data)(const gs_indexbuffer_t *indexbuffer);
 	size_t (*gs_indexbuffer_get_num_indices)(
 			const gs_indexbuffer_t *indexbuffer);

+ 19 - 0
libobs/graphics/graphics.c

@@ -2477,6 +2477,16 @@ void gs_vertexbuffer_flush(gs_vertbuffer_t *vertbuffer)
 	thread_graphics->exports.gs_vertexbuffer_flush(vertbuffer);
 }
 
+void gs_vertexbuffer_flush_direct(gs_vertbuffer_t *vertbuffer,
+		const struct gs_vb_data *data)
+{
+	if (!gs_valid_p2("gs_vertexbuffer_flush_direct", vertbuffer, data))
+		return;
+
+	thread_graphics->exports.gs_vertexbuffer_flush_direct(vertbuffer,
+			data);
+}
+
 struct gs_vb_data *gs_vertexbuffer_get_data(const gs_vertbuffer_t *vertbuffer)
 {
 	if (!gs_valid_p("gs_vertexbuffer_get_data", vertbuffer))
@@ -2505,6 +2515,15 @@ void   gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer)
 	thread_graphics->exports.gs_indexbuffer_flush(indexbuffer);
 }
 
+void   gs_indexbuffer_flush_direct(gs_indexbuffer_t *indexbuffer,
+		const void *data)
+{
+	if (!gs_valid_p2("gs_indexbuffer_flush_direct", indexbuffer, data))
+		return;
+
+	thread_graphics->exports.gs_indexbuffer_flush_direct(indexbuffer, data);
+}
+
 void  *gs_indexbuffer_get_data(const gs_indexbuffer_t *indexbuffer)
 {
 	if (!gs_valid_p("gs_indexbuffer_get_data", indexbuffer))

+ 4 - 0
libobs/graphics/graphics.h

@@ -718,11 +718,15 @@ EXPORT void     gs_samplerstate_destroy(gs_samplerstate_t *samplerstate);
 
 EXPORT void     gs_vertexbuffer_destroy(gs_vertbuffer_t *vertbuffer);
 EXPORT void     gs_vertexbuffer_flush(gs_vertbuffer_t *vertbuffer);
+EXPORT void     gs_vertexbuffer_flush_direct(gs_vertbuffer_t *vertbuffer,
+		const struct gs_vb_data *data);
 EXPORT struct gs_vb_data *gs_vertexbuffer_get_data(
 		const gs_vertbuffer_t *vertbuffer);
 
 EXPORT void     gs_indexbuffer_destroy(gs_indexbuffer_t *indexbuffer);
 EXPORT void     gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer);
+EXPORT void     gs_indexbuffer_flush_direct(gs_indexbuffer_t *indexbuffer,
+		const void *data);
 EXPORT void     *gs_indexbuffer_get_data(const gs_indexbuffer_t *indexbuffer);
 EXPORT size_t   gs_indexbuffer_get_num_indices(
 		const gs_indexbuffer_t *indexbuffer);