[Mesa-dev] [PATCH 10/11] d3d1x: implement new stream output interface

Christoph Bumiller e0425955 at student.tuwien.ac.at
Fri Dec 9 10:21:10 PST 2011


---
 .../state_trackers/d3d1x/dxgi/src/dxgi_native.cpp  |    4 +-
 .../state_trackers/d3d1x/gd3d11/d3d11_context.h    |  104 +++++++++++++-------
 .../state_trackers/d3d1x/gd3d11/d3d11_objects.h    |   25 +++++-
 .../state_trackers/d3d1x/gd3d11/d3d11_screen.h     |   86 ++++++++++++++--
 .../state_trackers/d3d1x/gd3d1x/d3d_enums.cpp      |    4 +-
 .../state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp    |   39 ++++++++
 .../state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h      |    1 +
 7 files changed, 213 insertions(+), 50 deletions(-)

diff --git a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
index 5f270cd..2828389 100644
--- a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
+++ b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
@@ -846,8 +846,8 @@ struct dxgi_blitter
 		pipe->bind_vs_state(pipe, vs);
 		if(pipe->bind_gs_state)
 			pipe->bind_gs_state(pipe, 0);
-		if(pipe->bind_stream_output_state)
-			pipe->bind_stream_output_state(pipe, 0);
+		if(pipe->set_stream_output_targets)
+			pipe->set_stream_output_targets(pipe, 0, NULL, 0);
 		pipe->set_fragment_sampler_views(pipe, 1, &view);
 
 		pipe->draw_vbo(pipe, &draw);
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
index 4055c54..8ea7ccc 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
@@ -58,7 +58,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 	refcnt_ptr<GalliumD3D11SamplerState, PtrTraits> samplers[D3D11_STAGES][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
 	refcnt_ptr<GalliumD3D11Buffer, PtrTraits> input_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
 	refcnt_ptr<GalliumD3D11RenderTargetView, PtrTraits> render_target_views[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
-	refcnt_ptr<GalliumD3D11Buffer, PtrTraits> so_targets[D3D11_SO_BUFFER_SLOT_COUNT];
+	refcnt_ptr<GalliumD3D11Buffer, PtrTraits> so_buffers[D3D11_SO_BUFFER_SLOT_COUNT];
 
 #if API >= 11
 	refcnt_ptr<ID3D11UnorderedAccessView, PtrTraits> cs_unordered_access_views[D3D11_PS_CS_UAV_REGISTER_COUNT];
@@ -67,7 +67,6 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 
 	D3D11_VIEWPORT viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
 	D3D11_RECT scissor_rects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
-	unsigned so_offsets[D3D11_SO_BUFFER_SLOT_COUNT];
 	D3D11_PRIMITIVE_TOPOLOGY primitive_topology;
 	DXGI_FORMAT index_format;
 	unsigned index_offset;
@@ -88,10 +87,9 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 	// derived state
 	int primitive_mode;
 	struct pipe_vertex_buffer vertex_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
-	struct pipe_resource* so_buffers[D3D11_SO_BUFFER_SLOT_COUNT];
+	struct pipe_stream_output_target* so_targets[D3D11_SO_BUFFER_SLOT_COUNT];
 	struct pipe_sampler_view* sampler_views[D3D11_STAGES][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
 	void* sampler_csos[D3D11_STAGES][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
-	struct pipe_resource* buffers[D3D11_SO_BUFFER_SLOT_COUNT];
 	unsigned num_shader_resource_views[D3D11_STAGES];
 	unsigned num_samplers[D3D11_STAGES];
 	unsigned num_vertex_buffers;
@@ -150,8 +148,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 			caps.gs = false;
 			caps.stages = 2;
 		}
-		if(!pipe->set_stream_output_buffers)
-			caps.so = false;
+		assert(!caps.so || pipe->set_stream_output_targets);
 		if(!pipe->set_geometry_sampler_views)
 			caps.stages_with_sampling &=~ (1 << PIPE_SHADER_GEOMETRY);
 		if(!pipe->set_fragment_sampler_views)
@@ -164,7 +161,6 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		// pipeline state
 		memset(viewports, 0, sizeof(viewports));
 		memset(scissor_rects, 0, sizeof(scissor_rects));
-		memset(so_offsets, 0, sizeof(so_offsets));
 		primitive_topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
 		index_format = DXGI_FORMAT_UNKNOWN;
 		index_offset = 0;
@@ -178,7 +174,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		// derived state
 		primitive_mode = 0;
 		memset(vertex_buffers, 0, sizeof(vertex_buffers));
-		memset(so_buffers, 0, sizeof(so_buffers));
+		memset(so_targets, 0, sizeof(so_buffers));
 		memset(sampler_views, 0, sizeof(sampler_views));
 		memset(sampler_csos, 0, sizeof(sampler_csos));
 		memset(num_shader_resource_views, 0, sizeof(num_shader_resource_views));
@@ -744,6 +740,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		info.instance_count = 1;
 		info.primitive_restart = TRUE;
 		info.restart_index = strip_cut_index;
+		info.count_from_stream_output = NULL;
 
 		pipe->draw_vbo(pipe, &info);
 	}
@@ -767,6 +764,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		info.start_instance = 0;
 		info.instance_count = 1;
 		info.primitive_restart = FALSE;
+		info.count_from_stream_output = NULL;
 
 		pipe->draw_vbo(pipe, &info);
 	}
@@ -794,6 +792,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		info.instance_count = instance_count;
 		info.primitive_restart = TRUE;
 		info.restart_index = strip_cut_index;
+		info.count_from_stream_output = NULL;
 
 		pipe->draw_vbo(pipe, &info);
 	}
@@ -819,6 +818,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		info.start_instance = start_instance_location;
 		info.instance_count = instance_count;
 		info.primitive_restart = FALSE;
+		info.count_from_stream_output = NULL;
 
 		pipe->draw_vbo(pipe, &info);
 	}
@@ -832,7 +832,21 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		if(update_flags)
 			update_state();
 
-		pipe->draw_stream_output(pipe, primitive_mode);
+		pipe_draw_info info;
+		info.mode = primitive_mode;
+		info.indexed = FALSE;
+		info.count = 0;
+		info.start = 0;
+		info.index_bias = 0;
+		info.min_index = 0;
+		info.max_index = ~0;
+		info.start_instance = 0;
+		info.instance_count = 1;
+		info.primitive_restart = FALSE;
+		info.restart_index = 0;
+		info.count_from_stream_output = input_buffers[0].p->so_target;
+
+		pipe->draw_vbo(pipe, &info);
 	}
 
 	virtual void STDMETHODCALLTYPE DrawIndexedInstancedIndirect(
@@ -864,6 +878,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		info.instance_count = data.instance_count;
 		info.primitive_restart = TRUE;
 		info.restart_index = strip_cut_index;
+		info.count_from_stream_output = NULL;
 
 		pipe->draw_vbo(pipe, &info);
 	}
@@ -895,6 +910,7 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		info.start_instance = 0;
 		info.instance_count = data.instance_count;
 		info.primitive_restart = FALSE;
+		info.count_from_stream_output = NULL;
 
 		pipe->draw_vbo(pipe, &info);
 	}
@@ -1293,34 +1309,53 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		const unsigned *new_offsets)
 	{
 		SYNCHRONIZED;
-		unsigned i;
+
+		unsigned new_count, i;
+		bool changed = false;
+
+		uint32_t append_mask = 0xffffffff;
+
 		if(!new_so_targets)
 			count = 0;
-		bool changed = false;
-		for(i = 0; i < count; ++i)
+		for(new_count = 0, i = 0; i < count; ++i)
 		{
-			ID3D11Buffer* buffer = new_so_targets[i];
-			if(buffer != so_targets[i].p || new_offsets[i] != so_offsets[i])
+			GalliumD3D11Buffer* buffer = static_cast<GalliumD3D11Buffer*>(new_so_targets[i]);
+
+			if(buffer != so_buffers[i].p)
 			{
-				so_buffers[i] = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0;
-				so_targets[i] = buffer;
-				so_offsets[i] = new_offsets[i];
 				changed = true;
+				so_buffers[i] = buffer;
+				so_targets[i] = buffer ? buffer->so_target : 0;
 			}
-		}
-		for(; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i)
-		{
-			if(so_targets[i].p || so_offsets[i])
+			if(!buffer)
+				continue;
+			new_count = i + 1;
+
+			if(new_offsets[i] == (unsigned)-1)
+			{
+				assert(so_targets[i]);
+				continue;
+			}
+			append_mask &= ~(1 << i);
+
+			if(!so_targets[i] || new_offsets[i] != so_targets[i]->buffer_offset)
 			{
+				pipe_so_target_reference(&buffer->so_target, NULL);
+				buffer->so_target = pipe->create_stream_output_target(
+					pipe, buffer->resource, new_offsets[i], buffer->resource->width0 - new_offsets[i]);
+				so_targets[i] = buffer->so_target;
 				changed = true;
-				so_targets[i] = (ID3D11Buffer*)0;
-				so_offsets[i] = 0;
 			}
 		}
-		num_so_targets = count;
+		if (i < num_so_targets) {
+			changed = true;
+			for(; i < num_so_targets; ++i)
+				so_buffers[i] = (GalliumD3D11Buffer*)0;
+		}
+		num_so_targets = new_count;
 
-		if(changed && caps.so)
-			pipe->set_stream_output_buffers(pipe, so_buffers, (int*)so_offsets, num_so_targets);
+		if(likely(caps.so) && (changed || append_mask != 0xffffffff))
+			pipe->set_stream_output_targets(pipe, num_so_targets, so_targets, append_mask);
 	}
 
 	virtual void STDMETHODCALLTYPE SOGetTargets(
@@ -1334,9 +1369,9 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		SYNCHRONIZED;
 		for(unsigned i = 0; i < count; ++i)
 		{
-			out_so_targets[i] = so_targets[i].ref();
+			out_so_targets[i] = so_buffers[i].ref();
 #if API < 11
-			out_offsets[i] = so_offsets[i];
+			out_offsets[i] = so_targets[i]->buffer_offset;
 #endif
 		}
 	}
@@ -1369,9 +1404,12 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 
 		GalliumD3D11Asynchronous<>* async = (GalliumD3D11Asynchronous<>*)iasync;
 		void* tmp_data = alloca(async->data_size);
+		memset(tmp_data, 0, async->data_size); // sizeof(BOOL) is 4, sizeof(boolean) is 1
 		boolean ret = pipe->get_query_result(pipe, async->query, !(get_data_flags & D3D11_ASYNC_GETDATA_DONOTFLUSH), tmp_data);
 		if(out_data)
+      {
 			memcpy(out_data, tmp_data, std::min(async->data_size, data_size));
+      }
 		return ret ? S_OK : S_FALSE;
 	}
 
@@ -1646,11 +1684,12 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		pipe->bind_vs_state(pipe, shaders[D3D11_STAGE_VS].p ? shaders[D3D11_STAGE_VS].p->object : default_shaders[PIPE_SHADER_VERTEX]);
 		if(caps.gs)
 			pipe->bind_gs_state(pipe, shaders[D3D11_STAGE_GS].p ? shaders[D3D11_STAGE_GS].p->object : default_shaders[PIPE_SHADER_GEOMETRY]);
+		if(caps.so && num_so_targets)
+			pipe->set_stream_output_targets(pipe, num_so_targets, so_targets, ~0);
 		set_framebuffer();
 		set_viewport();
 		set_clip();
 		set_render_condition();
-		// TODO: restore stream output
 
 		update_flags |= UPDATE_VERTEX_BUFFERS | (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_PS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_PS));
 	}
@@ -1669,8 +1708,8 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 		GalliumD3D11ShaderResourceView* view = (GalliumD3D11ShaderResourceView*)shader_resource_view;
 		if(caps.gs)
 			pipe->bind_gs_state(pipe, 0);
-		if(caps.so)
-			pipe->bind_stream_output_state(pipe, 0);
+		if(caps.so && num_so_targets)
+			pipe->set_stream_output_targets(pipe, 0, NULL, 0);
 		if(pipe->render_condition)
 			pipe->render_condition(pipe, 0, 0);
 		for(unsigned layer = view->object->u.tex.first_layer; layer <= view->object->u.tex.last_layer; ++layer)
@@ -1695,9 +1734,6 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
 				pipe->set_constant_buffer(pipe, s, i, constant_buffers[s][i].p ? constant_buffers[s][i].p->resource : 0);
 		}
 
-		if(caps.so)
-			pipe->set_stream_output_buffers(pipe, so_buffers, (int*)so_offsets, num_so_targets);
-
 		update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_VS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_VS));
 		update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_GS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_GS));
 
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h
index 7e4ea13..72c422a 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h
@@ -368,19 +368,40 @@ typedef GalliumD3D11TypedResource<ID3D11Texture3D, D3D11_TEXTURE3D_DESC, D3D11_R
 typedef GalliumD3D11TypedResource<ID3D11Buffer, D3D11_BUFFER_DESC, D3D11_RESOURCE_DIMENSION_BUFFER> GalliumD3D11BufferBase;
 
 #if API >= 11
-typedef GalliumD3D11BufferBase GalliumD3D11Buffer;
 typedef GalliumD3D11Texture1DBase GalliumD3D11Texture1D;
 typedef GalliumD3D11Texture2DBase GalliumD3D11Texture2D;
 typedef GalliumD3D11Texture3DBase GalliumD3D11Texture3D;
+
+struct GalliumD3D11Buffer : public GalliumD3D11BufferBase
+{
+	struct pipe_stream_output_target *so_target;
+
+	GalliumD3D11Buffer(GalliumD3D11Screen* device, struct pipe_resource* resource, const D3D11_BUFFER_DESC& desc, unsigned dxgi_usage)
+	: GalliumD3D11BufferBase(device, resource, desc, dxgi_usage), so_target(0)
+	{
+	}
+
+	~GalliumD3D11Buffer()
+	{
+		if(so_target)
+			pipe_so_target_reference(&so_target, NULL);
+	}
+};
 #else
 struct GalliumD3D10Buffer : public GalliumD3D10BufferBase
 {
+	struct pipe_stream_output_target *so_target;
+
 	GalliumD3D10Buffer(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_BUFFER_DESC& desc, unsigned dxgi_usage)
 	: GalliumD3D10BufferBase(device, resource, desc, dxgi_usage)
-	{}
+	{
+	}
 
 	~GalliumD3D10Buffer()
 	{
+		if(so_target)
+			pipe_so_target_reference(&so_target, NULL);
+
 		device->UnbindBuffer(this);
 	}
 
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
index 84d7471..5ba6099 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
@@ -72,13 +72,13 @@ static unsigned caps_dx_10_0[] = {
 	UTIL_CHECK_CAP(ANISOTROPIC_FILTER),
 	UTIL_CHECK_CAP(MIXED_COLORBUFFER_FORMATS),
 	UTIL_CHECK_CAP(FRAGMENT_COLOR_CLAMP_CONTROL),
-	UTIL_CHECK_CAP(STREAM_OUTPUT),
 	UTIL_CHECK_CAP(CONDITIONAL_RENDER),
 	UTIL_CHECK_CAP(PRIMITIVE_RESTART),
 	UTIL_CHECK_CAP(TGSI_INSTANCEID),
 	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
 	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),
 	UTIL_CHECK_INT(MAX_TEXTURE_ARRAY_LAYERS, 512),
+	UTIL_CHECK_INT(MAX_STREAM_OUTPUT_BUFFERS, 4),
 	UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
 	UTIL_CHECK_SHADER(GEOMETRY, MAX_CONST_BUFFERS, 14),
 	UTIL_CHECK_SHADER(GEOMETRY, MAX_TEXTURE_SAMPLERS, 16),
@@ -108,7 +108,7 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
 	{
 		memset(&screen_caps, 0, sizeof(screen_caps));
 		screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
-		screen_caps.so = !!screen->get_param(screen, PIPE_CAP_STREAM_OUTPUT);
+		screen_caps.so = screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) > 0;
 		screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY);
 		screen_caps.render_condition = screen->get_param(screen, PIPE_CAP_CONDITIONAL_RENDER);
 		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
@@ -1347,19 +1347,31 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
 		return S_OK;
 	}
 
+#define D3D1X_SHVER_GEOMETRY_SHADER 2 /* D3D11_SHVER_GEOMETRY_SHADER */
+
 	GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length
 #if API >= 11
 			, ID3D11ClassLinkage *class_linkage
 #endif
-			)
+			, struct pipe_stream_output_info* so_info)
 	{
 		bool dump = debug_get_option_dump_shaders();
 
+		std::auto_ptr<sm4_program> sm4(0);
+
 		dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length);
 		if(!sm4_chunk)
-			return 0;
-
-		std::auto_ptr<sm4_program> sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)));
+		{
+			if(so_info)
+				sm4.reset(new sm4_program());
+		}
+		else
+		{
+			sm4.reset(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)));
+			// check if this is a dummy GS, in which case we only need a place to store the signature
+			if(sm4.get() && so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER)
+				sm4.reset(new sm4_program());
+		}
 		if(!sm4.get())
 			return 0;
 
@@ -1382,7 +1394,13 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
 
 		struct pipe_shader_state tgsi_shader;
 		memset(&tgsi_shader, 0, sizeof(tgsi_shader));
-		tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4);
+		if(so_info)
+			memcpy(&tgsi_shader.stream_output, so_info, sizeof(tgsi_shader.stream_output));
+
+		if(so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER)
+			tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi_linkage_only(*sm4);
+		else
+			tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4);
 		if(!tgsi_shader.tokens)
 			return 0;
 
@@ -1435,7 +1453,7 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
 		ID3D11##Stage##Shader **out_shader) \
 	{ \
 		SYNCHRONIZED; \
-		GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \
+		GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS, NULL); \
 		if(!shader) \
 			return E_FAIL; \
 		if(out_shader) \
@@ -1483,10 +1501,58 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
 		ID3D11GeometryShader **out_geometry_shader)
 	{
 		SYNCHRONIZED;
+		GalliumD3D11GeometryShader* gs;
 
-		return E_NOTIMPL;
+#if API >= 11
+		if (rasterized_stream != 0)
+			return E_NOTIMPL; // not yet supported by gallium
+#endif
+		struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE);
+		if (!sig)
+			return E_INVALIDARG;
+		D3D11_SIGNATURE_PARAMETER_DESC* out;
+		unsigned num_outputs = dxbc_parse_signature(sig, &out);
+
+		struct pipe_stream_output_info so;
+		memset(&so, 0, sizeof(so));
 
-		// remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK
+#if API >= 11
+		if (num_strides)
+			so.stride = buffer_strides[0];
+		if (num_strides > 1)
+			debug_printf("Warning: multiple user-specified strides not implemented !\n");
+#else
+		so.stride = output_stream_stride;
+#endif
+
+		for(unsigned i = 0; i < num_entries; ++i)
+		{
+			unsigned j;
+			for(j = 0; j < num_outputs; ++j)
+				if(out[j].SemanticIndex == so_declaration[i].SemanticIndex && !strcasecmp(out[j].SemanticName, so_declaration[i].SemanticName))
+					break;
+			if(j >= num_outputs)
+				continue;
+			const int first_comp = ffs(out[j].Mask) - 1 + so_declaration[i].StartComponent;
+			so.output[i].output_buffer = so_declaration[i].OutputSlot;
+			so.output[i].register_index = out[j].Register;
+			so.output[i].register_mask = ((1 << so_declaration[i].ComponentCount) - 1) << first_comp;
+			++so.num_outputs;
+		}
+		if(out)
+			free(out);
+
+		gs = reinterpret_cast<GalliumD3D11GeometryShader*>(create_stage_shader(PIPE_SHADER_GEOMETRY, PASS_SHADER_ARGS, &so));
+		if (!gs)
+			return E_FAIL;
+
+		if (!out_geometry_shader) {
+			gs->Release();
+			return S_FALSE;
+		}
+		*out_geometry_shader = gs;
+
+		return S_OK;
 	}
 
 #if API >= 11
diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/d3d_enums.cpp b/src/gallium/state_trackers/d3d1x/gd3d1x/d3d_enums.cpp
index b8b3676..e531b0e 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d1x/d3d_enums.cpp
+++ b/src/gallium/state_trackers/d3d1x/gd3d1x/d3d_enums.cpp
@@ -107,11 +107,11 @@ unsigned d3d11_query_size[D3D11_QUERY_COUNT] =
 		sizeof(BOOL),
 		sizeof(UINT64),
 		sizeof(UINT64),
-		sizeof(UINT64),
+		sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT),
 		sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS),
 		sizeof(BOOL),
 		sizeof(D3D11_QUERY_DATA_SO_STATISTICS),
-		0,
+		sizeof(BOOL),
 		0,
 		0,
 		0,
diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp
index b541d92..392fd3e 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp
+++ b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.cpp
@@ -24,6 +24,7 @@
  *
  **************************************************************************/
 
+#include <d3d11shader.h>
 #include "d3d1xstutil.h"
 #include "sm4.h"
 #include "tgsi/tgsi_ureg.h"
@@ -819,3 +820,41 @@ void* sm4_to_tgsi(struct sm4_program& program)
 	sm4_to_tgsi_converter conv(program);
 	return conv.translate();
 }
+
+void* sm4_to_tgsi_linkage_only(struct sm4_program& prog)
+{
+	struct ureg_program* ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY);
+
+	uint64_t already = 0;
+	for(unsigned n = 0, i = 0; i < prog.num_params_out; ++i)
+	{
+		unsigned sn, si;
+
+		if(already & (1ULL << prog.params_out[i].Register))
+			continue;
+		already |= 1ULL << prog.params_out[i].Register;
+
+		switch(prog.params_out[i].SystemValueType)
+		{
+		case D3D_NAME_UNDEFINED:
+			sn = TGSI_SEMANTIC_GENERIC;
+			si = n++;
+			break;
+		case D3D_NAME_CULL_DISTANCE:
+		case D3D_NAME_CLIP_DISTANCE:
+			// FIXME
+			sn = 0;
+			si = prog.params_out[i].SemanticIndex;
+			assert(0);
+			break;
+		default:
+			continue;
+		}
+
+		ureg_DECL_output(ureg, sn, si);
+	}
+
+	const struct tgsi_token* tokens = ureg_get_tokens(ureg, 0);
+	ureg_destroy(ureg);
+	return (void*)tokens;
+}
diff --git a/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h
index 5722b27..c052420 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d1x/sm4_to_tgsi.h
@@ -30,5 +30,6 @@
 #include "sm4.h"
 
 void* sm4_to_tgsi(struct sm4_program& program);
+void* sm4_to_tgsi_linkage_only(struct sm4_program& program);
 
 #endif /* SM4_TO_TGSI_H_ */
-- 
1.7.3.4



More information about the mesa-dev mailing list