diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index c06741c561e15d05cb9e0049238b61995b329b4d..390001c5849419d546663e0b923689f7b7944d09 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -96,12 +96,6 @@ struct vkd3d_shader_sm4_parser
 
     unsigned int output_map[MAX_REG_OUTPUT];
 
-    struct vkd3d_shader_src_param src_param[SM4_MAX_SRC_COUNT];
-    struct vkd3d_shader_dst_param dst_param[SM4_MAX_DST_COUNT];
-    struct list src_free;
-    struct list src;
-    struct vkd3d_shader_immediate_constant_buffer icb;
-
     struct vkd3d_shader_parser p;
 };
 
@@ -206,7 +200,8 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv,
 static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, uint32_t opcode,
         uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
 {
-    shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &priv->src_param[0]);
+    shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT,
+            (struct vkd3d_shader_src_param *)&ins->src[0]);
     ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ?
             VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z;
 }
@@ -214,6 +209,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins,
 static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token,
         const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
 {
+    struct vkd3d_shader_immediate_constant_buffer *icb;
     enum vkd3d_sm4_shader_data_type type;
     unsigned int icb_size;
 
@@ -227,16 +223,24 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui
 
     ++tokens;
     icb_size = token_count - 1;
-    if (icb_size % 4 || icb_size > MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE)
+    if (icb_size % 4)
     {
         FIXME("Unexpected immediate constant buffer size %u.\n", icb_size);
         ins->handler_idx = VKD3DSIH_INVALID;
         return;
     }
 
-    priv->icb.vec4_count = icb_size / 4;
-    memcpy(priv->icb.data, tokens, sizeof(*tokens) * icb_size);
-    ins->declaration.icb = &priv->icb;
+    if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[icb_size]))))
+    {
+        ERR("Failed to allocate immediate constant buffer, size %u.\n", icb_size);
+        vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
+        ins->handler_idx = VKD3DSIH_INVALID;
+        return;
+    }
+    icb->vec4_count = icb_size / 4;
+    memcpy(icb->data, tokens, sizeof(*tokens) * icb_size);
+    shader_instruction_array_add_icb(&priv->p.instructions, icb);
+    ins->declaration.icb = icb;
 }
 
 static void shader_sm4_set_descriptor_register_range(struct vkd3d_shader_sm4_parser *sm4,
@@ -438,8 +442,9 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in
 static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token,
         const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
 {
-    priv->src_param[0].reg.u.fp_body_idx = *tokens++;
-    shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &priv->src_param[0]);
+    struct vkd3d_shader_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src;
+    src_params[0].reg.u.fp_body_idx = *tokens++;
+    shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]);
 }
 
 static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@@ -987,45 +992,18 @@ static enum vkd3d_data_type map_data_type(char t)
 static void shader_sm4_destroy(struct vkd3d_shader_parser *parser)
 {
     struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
-    struct vkd3d_shader_src_param_entry *e1, *e2;
 
-    list_move_head(&sm4->src_free, &sm4->src);
-    LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &sm4->src_free, struct vkd3d_shader_src_param_entry, entry)
-    {
-        vkd3d_free(e1);
-    }
+    shader_instruction_array_destroy(&parser->instructions);
     free_shader_desc(&parser->shader_desc);
     vkd3d_free(sm4);
 }
 
-static struct vkd3d_shader_src_param *get_src_param(struct vkd3d_shader_sm4_parser *priv)
-{
-    struct vkd3d_shader_src_param_entry *e;
-    struct list *elem;
-
-    if (!list_empty(&priv->src_free))
-    {
-        elem = list_head(&priv->src_free);
-        list_remove(elem);
-    }
-    else
-    {
-        if (!(e = vkd3d_malloc(sizeof(*e))))
-            return NULL;
-        elem = &e->entry;
-    }
-
-    list_add_tail(&priv->src, elem);
-    e = LIST_ENTRY(elem, struct vkd3d_shader_src_param_entry, entry);
-    return &e->param;
-}
-
 static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr,
         const uint32_t *end, uint32_t addressing, struct vkd3d_shader_register_index *reg_idx)
 {
     if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE)
     {
-        struct vkd3d_shader_src_param *rel_addr = get_src_param(priv);
+        struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&priv->p, 1);
 
         if (!(reg_idx->rel_addr = rel_addr))
         {
@@ -1468,14 +1446,14 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
     struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
     const struct vkd3d_sm4_opcode_info *opcode_info;
     uint32_t opcode_token, opcode, previous_token;
+    struct vkd3d_shader_dst_param *dst_params;
+    struct vkd3d_shader_src_param *src_params;
     const uint32_t **ptr = &parser->ptr;
     unsigned int i, len;
     size_t remaining;
     const uint32_t *p;
     DWORD precise;
 
-    list_move_head(&sm4->src_free, &sm4->src);
-
     if (*ptr >= sm4->end)
     {
         WARN("End of byte-code, failed to read opcode.\n");
@@ -1520,11 +1498,15 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
     ins->structured = false;
     ins->predicate = NULL;
     ins->dst_count = strnlen(opcode_info->dst_info, SM4_MAX_DST_COUNT);
-    ins->dst = sm4->dst_param;
     ins->src_count = strnlen(opcode_info->src_info, SM4_MAX_SRC_COUNT);
-    ins->src = sm4->src_param;
-    assert(ins->dst_count <= ARRAY_SIZE(sm4->dst_param));
-    assert(ins->src_count <= ARRAY_SIZE(sm4->src_param));
+    ins->src = src_params = shader_parser_get_src_params(parser, ins->src_count);
+    if (!src_params && ins->src_count)
+    {
+        ERR("Failed to allocate src parameters.\n");
+        vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
+        ins->handler_idx = VKD3DSIH_INVALID;
+        return;
+    }
     ins->resource_type = VKD3D_SHADER_RESOURCE_NONE;
     ins->resource_stride = 0;
     ins->resource_data_type[0] = VKD3D_DATA_FLOAT;
@@ -1538,6 +1520,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
 
     if (opcode_info->read_opcode_func)
     {
+        ins->dst = NULL;
         opcode_info->read_opcode_func(ins, opcode, opcode_token, p, len, sm4);
     }
     else
@@ -1557,21 +1540,29 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
         precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT;
         ins->flags |= precise << VKD3DSI_PRECISE_SHIFT;
 
+        ins->dst = dst_params = shader_parser_get_dst_params(parser, ins->dst_count);
+        if (!dst_params && ins->dst_count)
+        {
+            ERR("Failed to allocate dst parameters.\n");
+            vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
+            ins->handler_idx = VKD3DSIH_INVALID;
+            return;
+        }
         for (i = 0; i < ins->dst_count; ++i)
         {
             if (!(shader_sm4_read_dst_param(sm4, &p, *ptr, map_data_type(opcode_info->dst_info[i]),
-                    &sm4->dst_param[i])))
+                    &dst_params[i])))
             {
                 ins->handler_idx = VKD3DSIH_INVALID;
                 return;
             }
-            sm4->dst_param[i].modifiers |= instruction_dst_modifier;
+            dst_params[i].modifiers |= instruction_dst_modifier;
         }
 
         for (i = 0; i < ins->src_count; ++i)
         {
             if (!(shader_sm4_read_src_param(sm4, &p, *ptr, map_data_type(opcode_info->src_info[i]),
-                    &sm4->src_param[i])))
+                    &src_params[i])))
             {
                 ins->handler_idx = VKD3DSIH_INVALID;
                 return;
@@ -1594,20 +1585,12 @@ static bool shader_sm4_is_end(struct vkd3d_shader_parser *parser)
     return parser->ptr == sm4->end;
 }
 
-static void shader_sm4_reset(struct vkd3d_shader_parser *parser)
-{
-    struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
-
-    parser->ptr = sm4->start;
-    parser->failed = false;
-}
-
 static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
 {
-    .parser_reset = shader_sm4_reset,
+    .parser_reset = shader_parser_reset,
     .parser_destroy = shader_sm4_destroy,
-    .parser_read_instruction = shader_sm4_read_instruction,
-    .parser_is_end = shader_sm4_is_end,
+    .parser_read_instruction = shader_parser_read_instruction,
+    .parser_is_end = shader_parser_is_end,
 };
 
 static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code,
@@ -1670,6 +1653,10 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
     version.major = VKD3D_SM4_VERSION_MAJOR(version_token);
     version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
 
+    /* Estimate instruction count to avoid reallocation in most shaders. */
+    if (!shader_instruction_array_init(&sm4->p.instructions, token_count / 7u + 20))
+        return VKD3D_ERROR_OUT_OF_MEMORY;
+
     vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops);
     sm4->p.ptr = sm4->start;
 
@@ -1690,9 +1677,6 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
         sm4->output_map[e->register_index] = e->semantic_index;
     }
 
-    list_init(&sm4->src_free);
-    list_init(&sm4->src);
-
     return true;
 }
 
@@ -2061,7 +2045,9 @@ static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
 int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info,
         struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
 {
+    struct vkd3d_shader_instruction_array *instructions;
     struct vkd3d_shader_desc *shader_desc;
+    struct vkd3d_shader_instruction *ins;
     struct vkd3d_shader_sm4_parser *sm4;
     int ret;
 
@@ -2089,6 +2075,28 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
         return VKD3D_ERROR_INVALID_ARGUMENT;
     }
 
+    instructions = &sm4->p.instructions;
+    while (!shader_sm4_is_end(&sm4->p))
+    {
+        if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
+        {
+            ERR("Failed to allocate instructions.\n");
+            vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
+            shader_sm4_destroy(&sm4->p);
+            return VKD3D_ERROR_OUT_OF_MEMORY;
+        }
+        ins = &instructions->elements[instructions->count];
+        shader_sm4_read_instruction(&sm4->p, ins);
+
+        if (ins->handler_idx == VKD3DSIH_INVALID)
+        {
+            WARN("Encountered unrecognized or invalid instruction.\n");
+            shader_sm4_destroy(&sm4->p);
+            return VKD3D_ERROR_OUT_OF_MEMORY;
+        }
+        ++instructions->count;
+    }
+
     *parser = &sm4->p;
 
     return VKD3D_OK;
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index d5e7e7378bc13b5d355c7adb8b13c532f80b1f59..275bcf28ab18f3a52a918346f498de8b66a5369e 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -1679,9 +1679,24 @@ bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *ins
     return true;
 }
 
+bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions,
+        struct vkd3d_shader_immediate_constant_buffer *icb)
+{
+    if (!vkd3d_array_reserve((void **)&instructions->icbs, &instructions->icb_capacity, instructions->icb_count + 1,
+            sizeof(*instructions->icbs)))
+        return false;
+    instructions->icbs[instructions->icb_count++] = icb;
+    return true;
+}
+
 void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions)
 {
+    unsigned int i;
+
     vkd3d_free(instructions->elements);
     shader_param_allocator_destroy(&instructions->dst_params);
     shader_param_allocator_destroy(&instructions->src_params);
+    for (i = 0; i < instructions->icb_count; ++i)
+        vkd3d_free(instructions->icbs[i]);
+    vkd3d_free(instructions->icbs);
 }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 848ac45d3037369d39318bc5de563619640f3989..5d89c243daac1bf142924c5c7fdca5c117194a3a 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -71,6 +71,7 @@ enum vkd3d_shader_error
 
     VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF                = 1000,
     VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_RANGE       = 1001,
+    VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY                = 1002,
 
     VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
     VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE        = 2001,
@@ -619,7 +620,6 @@ enum vkd3d_shader_conditional_op
     VKD3D_SHADER_CONDITIONAL_OP_Z  = 1
 };
 
-#define MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE 4096
 #define MAX_REG_OUTPUT 32
 
 enum vkd3d_shader_type
@@ -649,7 +649,7 @@ struct vkd3d_shader_version
 struct vkd3d_shader_immediate_constant_buffer
 {
     unsigned int vec4_count;
-    uint32_t data[MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE];
+    uint32_t data[];
 };
 
 struct vkd3d_shader_indexable_temp
@@ -969,10 +969,15 @@ struct vkd3d_shader_instruction_array
 
     struct vkd3d_shader_param_allocator src_params;
     struct vkd3d_shader_param_allocator dst_params;
+    struct vkd3d_shader_immediate_constant_buffer **icbs;
+    size_t icb_capacity;
+    size_t icb_count;
 };
 
 bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve);
 bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve);
+bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions,
+        struct vkd3d_shader_immediate_constant_buffer *icb);
 void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions);
 
 struct vkd3d_shader_parser