Broadly this seems in the right direction. Patch 1/2 should be split though; for example:
- Parse d3dbc bytecode up-front into a shader instruction array. This could keep the existing vkd3d_shader_parser interface, and just iterate over the instruction in the array in shader_sm1_read_instruction(). shader_sm1_reset() and shader_sm1_is_end() would have obvious implementations as well. - Do the same for vkd3d_shader_sm4_parser. - Use the instruction array interface in vkd3d_dxbc_binary_to_text() - Likewise for scan_with_parser(). - The GLSL backend. - The SPIR-V backend.
That's 6 separate parts right there; it seems plausible that the vkd3d_shader_sm1_parser and vkd3d_shader_sm4_parser parts could be further split, but I haven't looked that close yet.
+ if (!shader_instruction_array_reserve(instructions, 1)) + { + ... + } + ins = &instructions->elements[instructions->count];
shader_instruction_array_reserve() seems a bit awkward, in part because of the similarity in name to vkd3d_array_reserve(), which gets passed the total size to reserve. It might be nicer to do something like "shader_instruction_array_reserve(instructions, instructions->count + 1)".
+struct vkd3d_shader_instruction_array +{ + struct vkd3d_shader_instruction *elements; + size_t capacity; + unsigned int count; + + struct vkd3d_shader_param_allocator src_params; + struct vkd3d_shader_param_allocator dst_params; +};
It seems odd to use different types for "capacity" and "count" above. Could we use size_t for both?
Patch 2/2 is a "vkd3d-shader/spirv" patch. I'd probably reframe it as doing the existing transformation on the vkd3d_shader_instruction IR instead of during translation to SPIR-V.
- while (!vkd3d_shader_parser_is_end(parser)) - { - vkd3d_shader_parser_read_instruction(parser, &instruction); - - if (instruction.handler_idx == VKD3DSIH_INVALID) - { - WARN("Encountered unrecognized or invalid instruction.\n"); - ret = VKD3D_ERROR_INVALID_SHADER; - break; - } - - if ((ret = spirv_compiler_handle_instruction(spirv_compiler, &instruction)) < 0) - break; - } - - if (parser->failed) - ret = VKD3D_ERROR_INVALID_SHADER; + ret = spirv_compiler_handle_instructions(spirv_compiler, &parser->instructions); if (ret >= 0) ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, out);
It's somewhat tangential to this series, but I think we should pass "parser" to spirv_compiler_generate_spirv(), and then just fold spirv_compiler_handle_instructions() into spirv_compiler_generate_spirv(), analogous to vkd3d_glsl_generator_generate().