vkd3d-shader/hlsl: Validate cbuffer register allocations.

This commit is contained in:
Victor Chiletto 2024-07-03 14:05:58 -03:00
parent 27414ef928
commit da36a447b8
Notes: Henri Verbeet 2024-07-08 18:04:49 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/792
2 changed files with 470 additions and 2 deletions

View File

@ -4925,6 +4925,14 @@ void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx)
} }
} }
static unsigned int get_max_cbuffer_reg_index(struct hlsl_ctx *ctx)
{
if (hlsl_version_ge(ctx, 5, 1))
return UINT_MAX;
return 13;
}
static void allocate_buffers(struct hlsl_ctx *ctx) static void allocate_buffers(struct hlsl_ctx *ctx)
{ {
struct hlsl_buffer *buffer; struct hlsl_buffer *buffer;
@ -4956,6 +4964,12 @@ static void allocate_buffers(struct hlsl_ctx *ctx)
{ {
const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx, const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx,
reservation->reg_space, reservation->reg_index); reservation->reg_space, reservation->reg_index);
unsigned int max_index = get_max_cbuffer_reg_index(ctx);
if (buffer->reservation.reg_index > max_index)
hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
"Buffer reservation cb%u exceeds target's maximum (cb%u).",
buffer->reservation.reg_index, max_index);
if (reserved_buffer && reserved_buffer != buffer) if (reserved_buffer && reserved_buffer != buffer)
{ {
@ -4980,9 +4994,14 @@ static void allocate_buffers(struct hlsl_ctx *ctx)
} }
else if (!reservation->reg_type) else if (!reservation->reg_type)
{ {
unsigned int max_index = get_max_cbuffer_reg_index(ctx);
while (get_reserved_buffer(ctx, 0, index)) while (get_reserved_buffer(ctx, 0, index))
++index; ++index;
if (index > max_index)
hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
"Too many buffers allocated, target's maximum is %u.", max_index);
buffer->reg.space = 0; buffer->reg.space = 0;
buffer->reg.index = index; buffer->reg.index = index;
if (hlsl_version_ge(ctx, 5, 1)) if (hlsl_version_ge(ctx, 5, 1))

View File

@ -433,7 +433,7 @@ probe (0, 0) rgba(2.0, 2.0, 2.0, 2.0)
[require] [require]
shader model >= 4.0 shader model >= 4.0
[pixel shader fail todo] [pixel shader fail]
cbuffer buf : register(b0manymanyletters) cbuffer buf : register(b0manymanyletters)
{ {
@ -451,7 +451,7 @@ float4 main() : sv_target
% DXC fails during parsing. % DXC fails during parsing.
[pixel shader fail todo] [pixel shader fail]
cbuffer buf : register(banana) cbuffer buf : register(banana)
{ {
float a; float a;
@ -497,3 +497,452 @@ float4 main() : sv_target
todo(glsl) draw quad todo(glsl) draw quad
if(sm<6) probe (0, 0) rgba(2.0, 2.0, 2.0, 2.0) if(sm<6) probe (0, 0) rgba(2.0, 2.0, 2.0, 2.0)
if(sm>=6) probe (0, 0) rgba(0.5, 0.5, 0.5, 0.5) if(sm>=6) probe (0, 0) rgba(0.5, 0.5, 0.5, 0.5)
% cbuffer reservation limits.
[pixel shader]
cbuffer buf0 : register(b0)
{
float a;
};
cbuffer buf1 : register(b1)
{
float b;
};
cbuffer buf2 : register(b2)
{
float c;
};
cbuffer buf3 : register(b3)
{
float d;
};
cbuffer buf4 : register(b4)
{
float e;
};
cbuffer buf5 : register(b5)
{
float f;
};
cbuffer buf6 : register(b6)
{
float g;
};
cbuffer buf7 : register(b7)
{
float h;
};
cbuffer buf8 : register(b8)
{
float i;
};
cbuffer buf9 : register(b9)
{
float j;
};
cbuffer buf10 : register(b10)
{
float k;
};
cbuffer buf11 : register(b11)
{
float l;
};
cbuffer buf12 : register(b12)
{
float m;
};
cbuffer buf13 : register(b13)
{
float n;
};
float4 main() : sv_target
{
return a * b * c * d * e * f * g * h * i * j * k * l * m * n;
}
[pixel shader fail(sm>=6)]
// $Globals and $Params count towards the 14 cbuffer limit.
float glob;
cbuffer buf0 : register(b0)
{
float a;
};
cbuffer buf1 : register(b1)
{
float b;
};
cbuffer buf2 : register(b2)
{
float c;
};
cbuffer buf3 : register(b3)
{
float d;
};
cbuffer buf4 : register(b4)
{
float e;
};
cbuffer buf5 : register(b5)
{
float f;
};
cbuffer buf6 : register(b6)
{
float g;
};
cbuffer buf7 : register(b7)
{
float h;
};
cbuffer buf8 : register(b8)
{
float i;
};
cbuffer buf9 : register(b9)
{
float j;
};
cbuffer buf10 : register(b10)
{
float k;
};
cbuffer buf11 : register(b11)
{
float l;
};
float4 main(uniform float param) : sv_target
{
return glob * param * a * b * c * d * e * f * g * h * i * j * k * l;
}
[pixel shader fail]
float glob;
cbuffer buf0 : register(b0)
{
float a;
};
cbuffer buf1 : register(b1)
{
float b;
};
cbuffer buf2 : register(b2)
{
float c;
};
cbuffer buf3 : register(b3)
{
float d;
};
cbuffer buf4 : register(b4)
{
float e;
};
cbuffer buf5 : register(b5)
{
float f;
};
cbuffer buf6 : register(b6)
{
float g;
};
cbuffer buf7 : register(b7)
{
float h;
};
cbuffer buf8 : register(b8)
{
float i;
};
cbuffer buf9 : register(b9)
{
float j;
};
cbuffer buf10 : register(b10)
{
float k;
};
cbuffer buf11 : register(b11)
{
float l;
};
cbuffer buf12 : register(b12)
{
float m;
};
float4 main(uniform float param) : sv_target
{
return glob * param * a * b * c * d * e * f * g * h * i * j * k * l * m;
}
[pixel shader fail todo]
// Unused cbuffers still reserve their slot, and count towards the limit.
float glob;
cbuffer buf0 : register(b0)
{
float a;
};
cbuffer buf1 : register(b1)
{
float b;
};
cbuffer buf2 : register(b2)
{
float c;
};
cbuffer buf3 : register(b3)
{
float d;
};
cbuffer buf4 : register(b4)
{
float e;
};
cbuffer buf5 : register(b5)
{
float f;
};
cbuffer buf6 : register(b6)
{
float g;
};
cbuffer buf7 : register(b7)
{
float h;
};
cbuffer buf8 : register(b8)
{
float i;
};
cbuffer buf9 : register(b9)
{
float j;
};
cbuffer buf10 : register(b10)
{
float k;
};
cbuffer buf11 : register(b11)
{
float l;
};
cbuffer buf12 : register(b12)
{
float m;
};
float4 main(uniform float param) : sv_target
{
return glob * param * a * b * c * d * e * f * g * h * i * j * k * l;
}
[require]
shader model >= 5.1
[pixel shader fail(sm>=6)]
// 5.1 and up have unlimited CBV slots.
float glob;
cbuffer buf0 : register(b0)
{
float a;
};
cbuffer buf1 : register(b1)
{
float b;
};
cbuffer buf2 : register(b2)
{
float c;
};
cbuffer buf3 : register(b3)
{
float d;
};
cbuffer buf4 : register(b4)
{
float e;
};
cbuffer buf5 : register(b5)
{
float f;
};
cbuffer buf6 : register(b6)
{
float g;
};
cbuffer buf7 : register(b7)
{
float h;
};
cbuffer buf8 : register(b8)
{
float i;
};
cbuffer buf9 : register(b9)
{
float j;
};
cbuffer buf10 : register(b10)
{
float k;
};
cbuffer buf11 : register(b11)
{
float l;
};
cbuffer buf12 : register(b12)
{
float m;
};
float4 main(uniform float param) : sv_target
{
return glob * param * a * b * c * d * e * f * g * h * i * j * k * l * m;
}
[pixel shader]
// SM6 doesn't support uniform parameters (why??)
float glob;
cbuffer buf0 : register(b0)
{
float a;
};
cbuffer buf1 : register(b1)
{
float b;
};
cbuffer buf2 : register(b2)
{
float c;
};
cbuffer buf3 : register(b3)
{
float d;
};
cbuffer buf4 : register(b4)
{
float e;
};
cbuffer buf5 : register(b5)
{
float f;
};
cbuffer buf6 : register(b6)
{
float g;
};
cbuffer buf7 : register(b7)
{
float h;
};
cbuffer buf8 : register(b8)
{
float i;
};
cbuffer buf9 : register(b9)
{
float j;
};
cbuffer buf10 : register(b10)
{
float k;
};
cbuffer buf11 : register(b11)
{
float l;
};
cbuffer buf12 : register(b12)
{
float m;
};
cbuffer buf13 : register(b13)
{
float n;
};
float4 main() : sv_target
{
return glob * a * b * c * d * e * f * g * h * i * j * k * l * m * n;
}