d3d1x: improve CreateInputLayout
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 13 Oct 2011 20:27:40 +0000 (22:27 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Fri, 21 Oct 2011 21:00:38 +0000 (23:00 +0200)
src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h

index dfa0d9e180441aa0592b6529679323cb2d8be530..1ccb0204da242c8c66c38e38b7e9806e6886fddb 100644 (file)
@@ -641,23 +641,60 @@ struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
 
                struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
 
-               unsigned num_params_to_use = std::min(num_params, (unsigned)D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT);
-               for(unsigned i = 0; i < num_params_to_use; ++i)
+               enum pipe_format formats[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
+               unsigned offsets[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
+
+               offsets[0] = 0;
+               for(unsigned i = 0; i < count; ++i)
+               {
+                       formats[i] = dxgi_to_pipe_format[input_element_descs[i].Format];
+
+                       if(likely(input_element_descs[i].AlignedByteOffset != D3D11_APPEND_ALIGNED_ELEMENT))
+                       {
+                               offsets[i] = input_element_descs[i].AlignedByteOffset;
+                       }
+                       else if(i > 0)
+                       {
+                               unsigned align_mask = util_format_description(formats[i])->channel[0].size;
+                               if(align_mask & 7) // e.g. R10G10B10A2
+                                       align_mask = 32;
+                               align_mask = (align_mask / 8) - 1;
+
+                               offsets[i] = (offsets[i - 1] + util_format_get_blocksize(formats[i - 1]) + align_mask) & ~align_mask;
+                       }
+               }
+
+               // TODO: check for & report errors (e.g. ambiguous layouts, unmatched semantics)
+
+               unsigned num_params_to_use = 0;
+               for(unsigned i = 0; i < num_params && num_params_to_use < D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT; ++i)
                {
-                       int idx = -1;
+                       if(!strcasecmp(params[i].SemanticName, "SV_INSTANCEID") ||
+                          !strcasecmp(params[i].SemanticName, "SV_VERTEXID"))
+                               continue;
+                       const unsigned n = num_params_to_use++;
+
                        semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex));
-                       if(iter != semantic_to_idx_map.end())
-                               idx = iter->second;
 
-                       // TODO: I kind of doubt Gallium drivers will like null elements; should we do something about it, either here, in the interface, or in the drivers?
-                       // TODO: also, in which cases should we return errors? (i.e. duplicate semantics in vs, duplicate semantics in layout, unmatched semantic in vs, unmatched semantic in layout)
-                       memset(&elements[i], 0, sizeof(elements[i]));
-                       if(idx >= 0)
+                       if(iter != semantic_to_idx_map.end())
+                       {
+                               unsigned idx = iter->second;
+
+                               elements[n].src_format = formats[idx];
+                               elements[n].src_offset = offsets[idx];
+                               elements[n].vertex_buffer_index = input_element_descs[idx].InputSlot;
+                               elements[n].instance_divisor = input_element_descs[idx].InstanceDataStepRate;
+                               if (input_element_descs[idx].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA)
+                                       if (elements[n].instance_divisor == 0)
+                                               elements[n].instance_divisor = ~0; // XXX: can't specify 'never' to gallium
+                       }
+                       else
                        {
-                               elements[i].src_format = dxgi_to_pipe_format[input_element_descs[idx].Format];
-                               elements[i].src_offset = input_element_descs[idx].AlignedByteOffset;
-                               elements[i].vertex_buffer_index = input_element_descs[idx].InputSlot;
-                               elements[i].instance_divisor = input_element_descs[idx].InstanceDataStepRate;
+                               // XXX: undefined input, is this valid or should we return an error ?
+                               elements[n].src_format = PIPE_FORMAT_NONE;
+                               elements[n].src_offset = 0;
+                               elements[n].vertex_buffer_index = 0;
+                               elements[n].instance_divisor = 0;
                        }
                }