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];
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;
// 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;
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)
// 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;
// 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));
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);
}
info.start_instance = 0;
info.instance_count = 1;
info.primitive_restart = FALSE;
+ info.count_from_stream_output = NULL;
pipe->draw_vbo(pipe, &info);
}
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);
}
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);
}
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(
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);
}
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);
}
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(
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
}
}
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;
}
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));
}
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)
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));
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),
{
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)
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;
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;
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) \
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