diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 52defccda0b5af3d706773cc5e9d15d9f768e5c9..5edd5c81f7a28affa2a6cb769217d54dcce7d750 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -21,9 +21,64 @@
 HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
         struct vkd3d_shader_code *spirv, uint32_t compiler_options)
 {
-    FIXME("Not implemented!\n");
+    struct vkd3d_dxbc_compiler *spirv_compiler;
+    struct vkd3d_shader_version shader_version;
+    struct vkd3d_shader_desc shader_desc;
+    struct vkd3d_shader_instruction ins;
+    void *parser_data;
+    const DWORD *ptr;
+    HRESULT hr;
+    bool ret;
 
-    return E_NOTIMPL;
+    TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x.\n",
+            dxbc->code, dxbc->size, spirv, compiler_options);
+
+    if (FAILED(hr = shader_extract_from_dxbc(dxbc->code, dxbc->size, &shader_desc)))
+    {
+        WARN("Failed to extract shader, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (!(parser_data = shader_sm4_init(shader_desc.byte_code, shader_desc.byte_code_size,
+            &shader_desc.output_signature)))
+    {
+        WARN("Failed to initialize shader parser, hr %#x.\n", hr);
+        free_shader_desc(&shader_desc);
+        return hr;
+    }
+
+    shader_sm4_read_header(parser_data, &ptr, &shader_version);
+
+    if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&shader_version, compiler_options)))
+    {
+        ERR("Failed to create DXBC compiler.\n");
+        shader_sm4_free(parser_data);
+        free_shader_desc(&shader_desc);
+        return hr;
+    }
+
+    while (!shader_sm4_is_end(parser_data, &ptr))
+    {
+        shader_sm4_read_instruction(parser_data, &ptr, &ins);
+
+        if (ins.handler_idx == VKD3DSIH_TABLE_SIZE)
+        {
+            WARN("Encountered unrecognized or invalid instruction.\n");
+            shader_sm4_free(parser_data);
+            free_shader_desc(&shader_desc);
+            vkd3d_dxbc_compiler_destroy(spirv_compiler);
+            return E_FAIL;
+        }
+
+        vkd3d_dxbc_compiler_handle_instruction(spirv_compiler, &ins);
+    }
+
+    ret = vkd3d_dxbc_compiler_generate_spirv(spirv_compiler, spirv);
+    vkd3d_dxbc_compiler_destroy(spirv_compiler);
+    shader_sm4_free(parser_data);
+    free_shader_desc(&shader_desc);
+
+    return ret ? S_OK : E_FAIL;
 }
 
 void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code)