Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2021
- 83 participants
- 2620 messages
Re: [PATCH vkd3d v2 5/7] tests: Return a failure code if unable to parse a shader_test file.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
The first hunk conflicts with current master, but it's easy to fix.
On 02/11/21 22:31, Zebediah Figura wrote:
> Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
> ---
> include/private/vkd3d_common.h | 2 +
> tests/shader_runner_d3d12.c | 70 +++++++++++++++-------------------
> 2 files changed, 33 insertions(+), 39 deletions(-)
>
> diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h
> index 18cc3cab2..482cabf96 100644
> --- a/include/private/vkd3d_common.h
> +++ b/include/private/vkd3d_common.h
> @@ -48,6 +48,7 @@ static inline size_t align(size_t addr, size_t alignment)
> }
>
> #ifdef __GNUC__
> +# define VKD3D_NORETURN __attribute__((noreturn))
> # if defined(__MINGW32__) && (defined(_UCRT) || __USE_MINGW_ANSI_STDIO)
> # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(gnu_printf, fmt, args)))
> # else
> @@ -55,6 +56,7 @@ static inline size_t align(size_t addr, size_t alignment)
> # endif
> # define VKD3D_UNUSED __attribute__((unused))
> #else
> +# define VKD3D_NORETURN
> # define VKD3D_PRINTF_FUNC(fmt, args)
> # define VKD3D_UNUSED
> #endif /* __GNUC__ */
> diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
> index d52382978..169271242 100644
> --- a/tests/shader_runner_d3d12.c
> +++ b/tests/shader_runner_d3d12.c
> @@ -45,6 +45,16 @@
> #include "d3d12_crosstest.h"
> #include <errno.h>
>
> +static void VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) fatal_error(const char *format, ...)
> +{
> + va_list args;
> +
> + va_start(args, format);
> + vfprintf(stderr, format, args);
> + va_end(args);
> + exit(1);
> +}
> +
> static bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
> {
> size_t new_capacity, max_capacity;
> @@ -201,10 +211,7 @@ static void parse_texture_format(struct texture *texture, const char *line)
> }
> }
>
> - fprintf(stderr, "Unknown format '%s'.\n", line);
> - texture->format = DXGI_FORMAT_R32G32B32A32_FLOAT;
> - texture->data_type = TEXTURE_DATA_FLOAT;
> - texture->texel_size = 16;
> + fatal_error("Unknown format '%s'.\n", line);
> }
>
> static D3D12_TEXTURE_ADDRESS_MODE parse_sampler_address_mode(const char *line, const char **rest)
> @@ -219,14 +226,12 @@ static D3D12_TEXTURE_ADDRESS_MODE parse_sampler_address_mode(const char *line, c
> return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
> if (match_string(line, "wrap", rest))
> return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
> - fprintf(stderr, "Malformed address mode '%s'.\n", line);
> - return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
> +
> + fatal_error("Unknown sampler address mode '%s'.\n", line);
> }
>
> static void parse_sampler_directive(struct sampler *sampler, const char *line)
> {
> - const char *const orig_line = line;
> -
> if (match_string(line, "address", &line))
> {
> sampler->u_address = parse_sampler_address_mode(line, &line);
> @@ -256,23 +261,22 @@ static void parse_sampler_directive(struct sampler *sampler, const char *line)
> for (i = 0; i < ARRAY_SIZE(filters); ++i)
> {
> if (match_string(line, filters[i].string, &line))
> + {
> sampler->filter = filters[i].filter;
> + return;
> + }
> }
> +
> + fatal_error("Unknown sampler filter '%s'.\n", line);
> }
> else
> {
> - goto err;
> + fatal_error("Unknown sampler directive '%s'.\n", line);
> }
> -
> - return;
> -
> -err:
> - fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
> }
>
> static void parse_texture_directive(struct texture *texture, const char *line)
> {
> - const char *const orig_line = line;
> int ret;
>
> if (match_string(line, "format", &line))
> @@ -283,7 +287,7 @@ static void parse_texture_directive(struct texture *texture, const char *line)
> {
> ret = sscanf(line, "( %u , %u )", &texture->width, &texture->height);
> if (ret < 2)
> - goto err;
> + fatal_error("Malformed texture size '%s'.\n", line);
> }
> else
> {
> @@ -323,17 +327,10 @@ static void parse_texture_directive(struct texture *texture, const char *line)
> line = rest;
> }
> }
> -
> - return;
> -
> -err:
> - fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
> }
>
> static void parse_test_directive(struct shader_context *context, const char *line)
> {
> - const char *const orig_line = line;
> -
> if (match_string(line, "draw quad", &line))
> {
> D3D12_SHADER_BYTECODE ps
> @@ -454,7 +451,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
>
> ret = sscanf(line, "( %f , %f , %f , %f ) %u", &v.x, &v.y, &v.z, &v.w, &ulps);
> if (ret < 4)
> - goto err;
> + fatal_error("Malformed probe arguments '%s'.\n", line);
> if (ret < 5)
> ulps = 0;
> check_sub_resource_vec4(context->c.render_target, 0, context->c.queue, context->c.list, &v, ulps);
> @@ -471,7 +468,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> ret = sscanf(line, "( %u , %u , %u , %u ) ( %f , %f , %f , %f ) %u",
> &x, &y, &w, &h, &v.x, &v.y, &v.z, &v.w, &ulps);
> if (ret < 8)
> - goto err;
> + fatal_error("Malformed probe arguments '%s'.\n", line);
> if (ret < 9)
> ulps = 0;
>
> @@ -494,7 +491,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
>
> ret = sscanf(line, "( %u , %u ) ( %f , %f , %f , %f ) %u", &x, &y, &v.x, &v.y, &v.z, &v.w, &ulps);
> if (ret < 6)
> - goto err;
> + fatal_error("Malformed probe arguments '%s'.\n", line);
> if (ret < 7)
> ulps = 0;
>
> @@ -512,7 +509,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> unsigned int offset;
>
> if (!sscanf(line, "%u", &offset))
> - goto err;
> + fatal_error("Unknown uniform type '%s'.\n", line);
> line = strchr(line, ' ') + 1;
>
> if (match_string(line, "float4", &line))
> @@ -520,7 +517,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> struct vec4 v;
>
> if (sscanf(line, "%f %f %f %f", &v.x, &v.y, &v.z, &v.w) < 4)
> - goto err;
> + fatal_error("Malformed float4 constant '%s'.\n", line);
> if (offset + 4 > context->uniform_count)
> {
> context->uniform_count = offset + 4;
> @@ -533,7 +530,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> float f;
>
> if (sscanf(line, "%f", &f) < 1)
> - goto err;
> + fatal_error("Malformed float constant '%s'.\n", line);
> if (offset + 1 > context->uniform_count)
> {
> context->uniform_count = offset + 1;
> @@ -546,7 +543,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> int i;
>
> if (sscanf(line, "%i", &i) < 1)
> - goto err;
> + fatal_error("Malformed int constant '%s'.\n", line);
> if (offset + 1 > context->uniform_count)
> {
> context->uniform_count = offset + 1;
> @@ -559,7 +556,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> unsigned int u;
>
> if (sscanf(line, "%u", &u) < 1)
> - goto err;
> + fatal_error("Malformed uint constant '%s'.\n", line);
> if (offset + 1 > context->uniform_count)
> {
> context->uniform_count = offset + 1;
> @@ -570,13 +567,8 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> }
> else
> {
> - goto err;
> + fatal_error("Unknown test directive '%s'.\n", line);
> }
> -
> - return;
> -
> -err:
> - fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
> }
>
> static struct sampler *get_sampler(struct shader_context *context, unsigned int slot)
> @@ -651,7 +643,7 @@ START_TEST(shader_runner_d3d12)
>
> if (!(f = fopen(filename, "r")))
> {
> - fprintf(stderr, "Unable to open '%s' for reading: %s\n", argv[1], strerror(errno));
> + fatal_error("Unable to open '%s' for reading: %s\n", argv[1], strerror(errno));
> return;
> }
>
> @@ -835,7 +827,7 @@ START_TEST(shader_runner_d3d12)
> switch (state)
> {
> case STATE_NONE:
> - fprintf(stderr, "Ignoring line '%s' in %s.\n", line, argv[1]);
> + fatal_error("Malformed line '%s'.\n", line);
> break;
>
> case STATE_PREPROC:
>
Nov. 3, 2021
Re: [PATCH vkd3d v2 4/7] tests: Add a shader test for texture sampling.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
On 02/11/21 22:31, Zebediah Figura wrote:
> Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
> ---
> Makefile.am | 2 +
> tests/sampler.shader_test | 34 +++++++++
> tests/shader_runner_d3d12.c | 136 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 172 insertions(+)
> create mode 100644 tests/sampler.shader_test
>
> diff --git a/Makefile.am b/Makefile.am
> index eaa4f8168..d6e14cf14 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -90,6 +90,7 @@ vkd3d_shader_tests = \
> tests/preproc-invalid.shader_test \
> tests/preproc-macro.shader_test \
> tests/preproc-misc.shader_test \
> + tests/sampler.shader_test \
> tests/saturate.shader_test \
> tests/swizzle-0.shader_test \
> tests/swizzle-1.shader_test \
> @@ -302,6 +303,7 @@ XFAIL_TESTS = \
> tests/hlsl-vector-indexing-uniform.shader_test \
> tests/math.shader_test \
> tests/max.shader_test \
> + tests/sampler.shader_test \
> tests/texture-load.shader_test \
> tests/texture-load-typed.shader_test \
> tests/trigonometry.shader_test \
> diff --git a/tests/sampler.shader_test b/tests/sampler.shader_test
> new file mode 100644
> index 000000000..3970fb510
> --- /dev/null
> +++ b/tests/sampler.shader_test
> @@ -0,0 +1,34 @@
> +[sampler 0]
> +filter linear linear linear
> +address clamp clamp clamp
> +
> +[texture 0]
> +size (2, 2)
> +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
> +0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0
> +
> +[pixel shader]
> +sampler s;
> +Texture2D t;
> +
> +float4 main() : sv_target
> +{
> + return t.Sample(s, float2(0.5, 0.5));
> +}
> +
> +[test]
> +draw quad
> +probe all rgba (0.25, 0, 0.25, 0)
> +
> +[pixel shader]
> +SamplerState s;
> +Texture2D t;
> +
> +float4 main() : sv_target
> +{
> + return t.Sample(s, float2(0.5, 0.5));
> +}
> +
> +[test]
> +draw quad
> +probe all rgba (0.25, 0, 0.25, 0)
> diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
> index a17a171ef..d52382978 100644
> --- a/tests/shader_runner_d3d12.c
> +++ b/tests/shader_runner_d3d12.c
> @@ -80,6 +80,14 @@ enum texture_data_type
> TEXTURE_DATA_UINT,
> };
>
> +struct sampler
> +{
> + unsigned int slot;
> +
> + D3D12_FILTER filter;
> + D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address;
> +};
> +
> struct texture
> {
> unsigned int slot;
> @@ -108,6 +116,9 @@ struct shader_context
>
> struct texture *textures;
> size_t texture_count;
> +
> + struct sampler *samplers;
> + size_t sampler_count;
> };
>
> static ID3D10Blob *compile_shader(const char *source, const char *target)
> @@ -139,6 +150,7 @@ enum parse_state
> STATE_NONE,
> STATE_PREPROC,
> STATE_PREPROC_INVALID,
> + STATE_SAMPLER,
> STATE_SHADER_INVALID_PIXEL,
> STATE_SHADER_PIXEL,
> STATE_TEXTURE,
> @@ -195,6 +207,69 @@ static void parse_texture_format(struct texture *texture, const char *line)
> texture->texel_size = 16;
> }
>
> +static D3D12_TEXTURE_ADDRESS_MODE parse_sampler_address_mode(const char *line, const char **rest)
> +{
> + if (match_string(line, "border", rest))
> + return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
> + if (match_string(line, "clamp", rest))
> + return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
> + if (match_string(line, "mirror_once", rest))
> + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE;
> + if (match_string(line, "mirror", rest))
> + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
> + if (match_string(line, "wrap", rest))
> + return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
> + fprintf(stderr, "Malformed address mode '%s'.\n", line);
> + return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
> +}
> +
> +static void parse_sampler_directive(struct sampler *sampler, const char *line)
> +{
> + const char *const orig_line = line;
> +
> + if (match_string(line, "address", &line))
> + {
> + sampler->u_address = parse_sampler_address_mode(line, &line);
> + sampler->v_address = parse_sampler_address_mode(line, &line);
> + sampler->w_address = parse_sampler_address_mode(line, &line);
> + }
> + else if (match_string(line, "filter", &line))
> + {
> + static const struct
> + {
> + const char *string;
> + D3D12_FILTER filter;
> + }
> + filters[] =
> + {
> + {"point point point", D3D12_FILTER_MIN_MAG_MIP_POINT},
> + {"point point linear", D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR},
> + {"point linear point", D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT},
> + {"point linear linear", D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR},
> + {"linear point point", D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT},
> + {"linear point linear", D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR},
> + {"linear linear point", D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT},
> + {"linear linear linear", D3D12_FILTER_MIN_MAG_MIP_LINEAR},
> + };
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(filters); ++i)
> + {
> + if (match_string(line, filters[i].string, &line))
> + sampler->filter = filters[i].filter;
> + }
> + }
> + else
> + {
> + goto err;
> + }
> +
> + return;
> +
> +err:
> + fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
> +}
> +
> static void parse_texture_directive(struct texture *texture, const char *line)
> {
> const char *const orig_line = line;
> @@ -266,6 +341,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> ID3D12GraphicsCommandList *command_list = context->c.list;
> D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
> D3D12_ROOT_PARAMETER root_params[3], *root_param;
> + D3D12_STATIC_SAMPLER_DESC static_samplers[1];
> static const float clear_color[4];
> unsigned int uniform_index;
> ID3D12PipelineState *pso;
> @@ -274,6 +350,8 @@ static void parse_test_directive(struct shader_context *context, const char *lin
>
> root_signature_desc.NumParameters = 0;
> root_signature_desc.pParameters = root_params;
> + root_signature_desc.NumStaticSamplers = 0;
> + root_signature_desc.pStaticSamplers = static_samplers;
>
> if (context->uniform_count)
> {
> @@ -324,6 +402,21 @@ static void parse_test_directive(struct shader_context *context, const char *lin
>
> assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params));
>
> + for (i = 0; i < context->sampler_count; ++i)
> + {
> + D3D12_STATIC_SAMPLER_DESC *sampler_desc = &static_samplers[root_signature_desc.NumStaticSamplers++];
> + const struct sampler *sampler = &context->samplers[i];
> +
> + memset(sampler_desc, 0, sizeof(*sampler_desc));
> + sampler_desc->Filter = sampler->filter;
> + sampler_desc->AddressU = sampler->u_address;
> + sampler_desc->AddressV = sampler->v_address;
> + sampler_desc->AddressW = sampler->w_address;
> + sampler_desc->ShaderRegister = sampler->slot;
> + sampler_desc->RegisterSpace = 0;
> + sampler_desc->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
> + }
> +
> if (context->c.root_signature)
> ID3D12RootSignature_Release(context->c.root_signature);
> hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature);
> @@ -486,6 +579,22 @@ err:
> fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
> }
>
> +static struct sampler *get_sampler(struct shader_context *context, unsigned int slot)
> +{
> + struct sampler *sampler;
> + size_t i;
> +
> + for (i = 0; i < context->sampler_count; ++i)
> + {
> + sampler = &context->samplers[i];
> +
> + if (sampler->slot == slot)
> + return sampler;
> + }
> +
> + return NULL;
> +}
> +
> static struct texture *get_texture(struct shader_context *context, unsigned int slot)
> {
> struct texture *texture;
> @@ -513,6 +622,7 @@ START_TEST(shader_runner_d3d12)
> size_t shader_source_size = 0, shader_source_len = 0;
> enum parse_state state = STATE_NONE;
> unsigned int i, line_number = 0;
> + struct sampler *current_sampler;
> struct texture *current_texture;
> struct shader_context context;
> const char *filename = NULL;
> @@ -559,6 +669,7 @@ START_TEST(shader_runner_d3d12)
> switch (state)
> {
> case STATE_NONE:
> + case STATE_SAMPLER:
> case STATE_TEST:
> case STATE_TEXTURE:
> break;
> @@ -663,6 +774,27 @@ START_TEST(shader_runner_d3d12)
> {
> state = STATE_SHADER_INVALID_PIXEL;
> }
> + else if (sscanf(line, "[sampler %u]\n", &index))
> + {
> + state = STATE_SAMPLER;
> +
> + if ((current_sampler = get_sampler(&context, index)))
> + {
> + memset(current_sampler, 0, sizeof(*current_sampler));
> + }
> + else
> + {
> + context.samplers = realloc(context.samplers,
> + ++context.sampler_count * sizeof(*context.samplers));
> + current_sampler = &context.samplers[context.sampler_count - 1];
> + memset(current_sampler, 0, sizeof(*current_sampler));
> + }
> + current_sampler->slot = index;
> + current_sampler->filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
> + current_sampler->u_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
> + current_sampler->v_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
> + current_sampler->w_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
> + }
> else if (sscanf(line, "[texture %u]\n", &index))
> {
> state = STATE_TEXTURE;
> @@ -719,6 +851,10 @@ START_TEST(shader_runner_d3d12)
> break;
> }
>
> + case STATE_SAMPLER:
> + parse_sampler_directive(current_sampler, line);
> + break;
> +
> case STATE_TEXTURE:
> parse_texture_directive(current_texture, line);
> break;
>
Nov. 3, 2021
Re: [PATCH vkd3d v2 3/7] tests: Allow using multiple [test] directives in the same shader_test file.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
On 02/11/21 22:31, Zebediah Figura wrote:
> Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
> ---
> tests/shader_runner_d3d12.c | 30 +++++++++++++++++++-----------
> 1 file changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
> index e47083765..a17a171ef 100644
> --- a/tests/shader_runner_d3d12.c
> +++ b/tests/shader_runner_d3d12.c
> @@ -305,17 +305,21 @@ static void parse_test_directive(struct shader_context *context, const char *lin
> range->RegisterSpace = 0;
> range->OffsetInDescriptorsFromTableStart = 0;
>
> - texture->heap = create_gpu_descriptor_heap(context->c.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
> - texture->resource = create_default_texture(context->c.device, texture->width, texture->height,
> - texture->format, 0, D3D12_RESOURCE_STATE_COPY_DEST);
> - resource_data.pData = texture->data;
> - resource_data.SlicePitch = resource_data.RowPitch = texture->width * texture->texel_size;
> - upload_texture_data(texture->resource, &resource_data, 1, context->c.queue, command_list);
> - reset_command_list(command_list, context->c.allocator);
> - transition_resource_state(command_list, texture->resource, D3D12_RESOURCE_STATE_COPY_DEST,
> - D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
> - ID3D12Device_CreateShaderResourceView(context->c.device, texture->resource,
> - NULL, get_cpu_descriptor_handle(&context->c, texture->heap, 0));
> + if (!texture->resource)
> + {
> + texture->heap = create_gpu_descriptor_heap(context->c.device,
> + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
> + texture->resource = create_default_texture(context->c.device, texture->width, texture->height,
> + texture->format, 0, D3D12_RESOURCE_STATE_COPY_DEST);
> + resource_data.pData = texture->data;
> + resource_data.SlicePitch = resource_data.RowPitch = texture->width * texture->texel_size;
> + upload_texture_data(texture->resource, &resource_data, 1, context->c.queue, command_list);
> + reset_command_list(command_list, context->c.allocator);
> + transition_resource_state(command_list, texture->resource, D3D12_RESOURCE_STATE_COPY_DEST,
> + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
> + ID3D12Device_CreateShaderResourceView(context->c.device, texture->resource,
> + NULL, get_cpu_descriptor_handle(&context->c, texture->heap, 0));
> + }
> }
>
> assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params));
> @@ -650,6 +654,10 @@ START_TEST(shader_runner_d3d12)
> if (!strcmp(line, "[pixel shader]\n"))
> {
> state = STATE_SHADER_PIXEL;
> +
> + if (context.ps_code)
> + ID3D10Blob_Release(context.ps_code);
> + context.ps_code = NULL;
> }
> else if (!strcmp(line, "[pixel shader fail]\n"))
> {
>
Nov. 3, 2021
Re: [PATCH vkd3d v2 2/7] vkd3d-shader/hlsl: Write SM4 image load instructions.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
On 02/11/21 22:31, Zebediah Figura wrote:
> Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
> ---
> libs/vkd3d-shader/hlsl_sm4.c | 95 +++++++++++++++++++++++++++++++++---
> 1 file changed, 88 insertions(+), 7 deletions(-)
>
> diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
> index f8eb0a1ef..5ab7df5f9 100644
> --- a/libs/vkd3d-shader/hlsl_sm4.c
> +++ b/libs/vkd3d-shader/hlsl_sm4.c
> @@ -763,6 +763,7 @@ static unsigned int sm4_swizzle_type(enum vkd3d_sm4_register_type type)
>
> case VKD3D_SM4_RT_CONSTBUFFER:
> case VKD3D_SM4_RT_INPUT:
> + case VKD3D_SM4_RT_RESOURCE:
> case VKD3D_SM4_RT_TEMP:
> return VKD3D_SM4_SWIZZLE_VEC4;
>
> @@ -779,14 +780,26 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
>
> if (var->is_uniform)
> {
> - unsigned int offset = hlsl_offset_from_deref(deref) + var->buffer_offset;
> + if (data_type->type == HLSL_CLASS_OBJECT && data_type->base_type == HLSL_TYPE_TEXTURE)
> + {
> + reg->type = VKD3D_SM4_RT_RESOURCE;
> + reg->dim = VKD3D_SM4_DIMENSION_VEC4;
> + reg->idx[0] = var->reg.id;
> + reg->idx_count = 1;
> + *writemask = VKD3DSP_WRITEMASK_ALL;
> + }
> + else
> + {
> + unsigned int offset = hlsl_offset_from_deref(deref) + var->buffer_offset;
>
> - reg->type = VKD3D_SM4_RT_CONSTBUFFER;
> - reg->dim = VKD3D_SM4_DIMENSION_VEC4;
> - reg->idx[0] = var->buffer->reg.id;
> - reg->idx[1] = offset / 4;
> - reg->idx_count = 2;
> - *writemask = ((1u << data_type->dimx) - 1) << (offset & 3);
> + assert(data_type->type <= HLSL_CLASS_VECTOR);
> + reg->type = VKD3D_SM4_RT_CONSTBUFFER;
> + reg->dim = VKD3D_SM4_DIMENSION_VEC4;
> + reg->idx[0] = var->buffer->reg.id;
> + reg->idx[1] = offset / 4;
> + reg->idx_count = 2;
> + *writemask = ((1u << data_type->dimx) - 1) << (offset & 3);
> + }
> }
> else if (var->is_input_semantic)
> {
> @@ -1154,6 +1167,50 @@ static void write_sm4_constant(struct hlsl_ctx *ctx,
> write_sm4_instruction(buffer, &instr);
> }
>
> +static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
> + const struct hlsl_type *resource_type, const struct hlsl_ir_node *dst,
> + const struct hlsl_deref *resource, const struct hlsl_ir_node *coords)
> +{
> + struct sm4_instruction instr;
> + unsigned int writemask;
> +
> + memset(&instr, 0, sizeof(instr));
> + instr.opcode = VKD3D_SM4_OP_LD;
> +
> + sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, dst);
> + instr.dst_count = 1;
> +
> + sm4_register_from_node(&instr.srcs[0].reg, &writemask, coords);
> + instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
> +
> + /* Mipmap level is in the last component in the IR, but needs to be in the W
> + * component in the instruction. */
> + switch (resource_type->sampler_dim)
> + {
> + case HLSL_SAMPLER_DIM_1D:
> + instr.srcs[0].swizzle = hlsl_combine_swizzles(instr.srcs[0].swizzle, HLSL_SWIZZLE(X, X, X, Y), 4);
> + break;
> +
> + case HLSL_SAMPLER_DIM_2D:
> + instr.srcs[0].swizzle = hlsl_combine_swizzles(instr.srcs[0].swizzle, HLSL_SWIZZLE(X, Y, X, Z), 4);
> + break;
> +
> + case HLSL_SAMPLER_DIM_3D:
> + case HLSL_SAMPLER_DIM_CUBE:
> + break;
> +
> + case HLSL_SAMPLER_DIM_GENERIC:
> + assert(0);
> + }
> +
> + sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask, resource, resource_type);
> + instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
> +
> + instr.src_count = 2;
> +
> + write_sm4_instruction(buffer, &instr);
> +}
> +
> static void write_sm4_expr(struct hlsl_ctx *ctx,
> struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_expr *expr)
> {
> @@ -1375,6 +1432,26 @@ static void write_sm4_load(struct hlsl_ctx *ctx,
> write_sm4_instruction(buffer, &instr);
> }
>
> +static void write_sm4_resource_load(struct hlsl_ctx *ctx,
> + struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_resource_load *load)
> +{
> + const struct hlsl_type *resource_type = load->resource.var->data_type;
> + const struct hlsl_ir_node *coords = load->coords.node;
> +
> + if (!load->resource.var->is_uniform)
> + {
> + hlsl_fixme(ctx, load->node.loc, "Load from non-uniform resource variable.");
> + return;
> + }
> +
> + switch (load->load_type)
> + {
> + case HLSL_RESOURCE_LOAD:
> + write_sm4_ld(ctx, buffer, resource_type, &load->node, &load->resource, coords);
> + break;
> + }
> +}
> +
> static void write_sm4_store(struct hlsl_ctx *ctx,
> struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_store *store)
> {
> @@ -1504,6 +1581,10 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
> write_sm4_load(ctx, &buffer, hlsl_ir_load(instr));
> break;
>
> + case HLSL_IR_RESOURCE_LOAD:
> + write_sm4_resource_load(ctx, &buffer, hlsl_ir_resource_load(instr));
> + break;
> +
> case HLSL_IR_STORE:
> write_sm4_store(ctx, &buffer, hlsl_ir_store(instr));
> break;
>
Nov. 3, 2021
Re: [PATCH vkd3d v2 1/7] vkd3d-shader/hlsl: Define a symbolic constant to represent the D3D_SIF_TEXTURE_COMPONENTS shift.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
On 02/11/21 22:31, Zebediah Figura wrote:
> Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
> ---
> libs/vkd3d-shader/hlsl_sm4.c | 2 +-
> libs/vkd3d-shader/sm4.h | 3 +++
> 2 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
> index 9d45e1633..f8eb0a1ef 100644
> --- a/libs/vkd3d-shader/hlsl_sm4.c
> +++ b/libs/vkd3d-shader/hlsl_sm4.c
> @@ -561,7 +561,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
> put_u32(&buffer, sm4_resource_format(var->data_type));
> put_u32(&buffer, sm4_rdef_resource_dimension(var->data_type));
> put_u32(&buffer, ~0u); /* FIXME: multisample count */
> - flags |= (var->data_type->e.resource_format->dimx - 1) << 2;
> + flags |= (var->data_type->e.resource_format->dimx - 1) << VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT;
> }
> put_u32(&buffer, var->reg.id);
> put_u32(&buffer, 1); /* bind count */
> diff --git a/libs/vkd3d-shader/sm4.h b/libs/vkd3d-shader/sm4.h
> index ddcb9a861..17a08ee27 100644
> --- a/libs/vkd3d-shader/sm4.h
> +++ b/libs/vkd3d-shader/sm4.h
> @@ -526,4 +526,7 @@ enum vkd3d_sm4_shader_data_type
> VKD3D_SM4_SHADER_DATA_MESSAGE = 0x4,
> };
>
> +/* The shift that corresponds to the D3D_SIF_TEXTURE_COMPONENTS mask. */
> +#define VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT 2
> +
> #endif /* __VKD3D_SM4_H */
>
Nov. 3, 2021
Re: [PATCH v5 2/4] ntdll: Implement RtlWalkFrameChain() for x86 and x86_64.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=101233
Your paranoid android.
=== w10pro64 (64 bit report) ===
ntdll:
exception.c:4406: Test failed: cs32: got eip 77a52a2c / 77a52a2c
=== debiant2 (32 bit Chinese:China report) ===
ntdll:
virtual: Timeout
Nov. 3, 2021
[PATCH v5 4/4] ntdll: Don't return the last NULL address when capturing frames.
by Paul Gofman
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/ntdll/signal_i386.c | 2 +-
dlls/ntdll/signal_x86_64.c | 2 +-
dlls/ntdll/tests/exception.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index b28684839b7..5613af4bce0 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -496,7 +496,7 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
for (i = 0; i < count; i++)
{
- if (!is_valid_frame( frame )) break;
+ if (!is_valid_frame( frame ) || !frame[1]) break;
if (i >= skip)
{
buffer[num_entries++] = (void *)frame[1];
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 4a9c7d4b9ff..0b6bbc09ed0 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1516,7 +1516,7 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, &context );
if (status != STATUS_SUCCESS) break;
- if (!dispatch.EstablisherFrame) break;
+ if (!dispatch.EstablisherFrame || !context.Rip) break;
if ((dispatch.EstablisherFrame & 7) ||
dispatch.EstablisherFrame < (ULONG64)NtCurrentTeb()->Tib.StackLimit ||
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 6e57c94703c..60f5472793f 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -9143,7 +9143,7 @@ static void test_walk_stack(void)
{
ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]);
}
- todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n");
+ ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n");
for (requested_count = frame_count - 1; requested_count <= frame_count + 1; ++requested_count)
{
--
2.31.1
Nov. 3, 2021
[PATCH v5 3/4] ntdll: Also capture first frame in back trace on x86.
by Paul Gofman
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/ntdll/signal_i386.c | 5 +----
dlls/ntdll/tests/exception.c | 2 --
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index ff3e837c784..b28684839b7 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -490,9 +490,6 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
ULONG *frame;
ULONG num_entries = 0;
- ++skip;
- ++count;
-
RtlCaptureContext( &context );
if (hash) *hash = 0;
frame = (ULONG *)context.Ebp;
@@ -507,7 +504,7 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
}
frame = (ULONG *)*frame;
}
- return i ? i - 1 : 0;
+ return i;
}
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 6f3b08b5ea6..6e57c94703c 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -9134,10 +9134,8 @@ static void test_walk_stack(void)
start = test_walk_stack;
end = (BYTE *)start + 0x1000;
- todo_wine_if(sizeof(void *) == 4)
ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
start, end, addrs[0]);
- todo_wine_if(sizeof(void *) == 4)
ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
start, end, addrs2[0]);
--
2.31.1
Nov. 3, 2021
[PATCH v5 2/4] ntdll: Implement RtlWalkFrameChain() for x86 and x86_64.
by Paul Gofman
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
v5:
- also test for requested_count == frame_count + 1.
dlls/ntdll/exception.c | 24 ++++++++-
dlls/ntdll/ntdll.spec | 2 +-
dlls/ntdll/signal_i386.c | 17 +++---
dlls/ntdll/signal_x86_64.c | 7 +--
dlls/ntdll/tests/exception.c | 83 +++++++++++++++++++++++++++++
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +-
include/ddk/ntddk.h | 3 ++
include/winnt.h | 2 +
8 files changed, 124 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index e956d8a722f..b020b829ae7 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -30,6 +30,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"
+#include "ddk/ntddk.h"
#include "ddk/wdm.h"
#include "wine/exception.h"
#include "wine/list.h"
@@ -1074,6 +1075,25 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
{
ULONG ret;
- ret = capture_stack_back_trace( skip, count, buffer, hash );
- return min( ret, (USHORT)~0 );
+ ret = capture_stack_back_trace( skip, skip + count, buffer, hash );
+ if (ret < skip) return 0;
+ return min( ret - skip, (USHORT)~0 );
+}
+
+
+/**********************************************************************
+ * RtlWalkFrameChain (NTDLL.@)
+ */
+ULONG WINAPI RtlWalkFrameChain( void **callers, ULONG count, ULONG skip )
+{
+ TRACE( "callers %p, count %u, skip %#x.\n", callers, count, skip );
+
+ if (skip & ~(0xff << RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT))
+ {
+ WARN( "Invalid flags %#x.\n", skip );
+ return 0;
+ }
+ skip >>= RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT;
+
+ return capture_stack_back_trace( skip, count, callers, NULL );
}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 13e65f65139..c54b2e205aa 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1073,7 +1073,7 @@
@ stdcall RtlWakeAddressSingle(ptr)
@ stdcall RtlWakeAllConditionVariable(ptr)
@ stdcall RtlWakeConditionVariable(ptr)
-@ stub RtlWalkFrameChain
+@ stdcall RtlWalkFrameChain(ptr long long)
@ stdcall RtlWalkHeap(long ptr)
@ stdcall RtlWow64EnableFsRedirection(long)
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 26150ce877b..ff3e837c784 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -488,27 +488,26 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
CONTEXT context;
ULONG i;
ULONG *frame;
+ ULONG num_entries = 0;
++skip;
+ ++count;
RtlCaptureContext( &context );
if (hash) *hash = 0;
frame = (ULONG *)context.Ebp;
- while (skip--)
- {
- if (!is_valid_frame( frame )) return 0;
- frame = (ULONG *)*frame;
- }
-
for (i = 0; i < count; i++)
{
if (!is_valid_frame( frame )) break;
- buffer[i] = (void *)frame[1];
- if (hash) *hash += frame[1];
+ if (i >= skip)
+ {
+ buffer[num_entries++] = (void *)frame[1];
+ if (hash) *hash += frame[1];
+ }
frame = (ULONG *)*frame;
}
- return i;
+ return i ? i - 1 : 0;
}
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 5f3c8f70208..4a9c7d4b9ff 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1504,16 +1504,17 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
TRACE( "(%u, %u, %p, %p)\n", skip, count, buffer, hash );
++skip;
+ ++count;
RtlCaptureContext( &context );
dispatch.TargetIp = 0;
dispatch.ContextRecord = &context;
dispatch.HistoryTable = &table;
if (hash) *hash = 0;
- for (i = 0; i < skip + count; i++)
+ for (i = 0; i < count; i++)
{
status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, &context );
- if (status != STATUS_SUCCESS) return i;
+ if (status != STATUS_SUCCESS) break;
if (!dispatch.EstablisherFrame) break;
@@ -1532,7 +1533,7 @@ ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, U
}
if (hash && num_entries > 0) *hash = hash_pointers( buffer, num_entries );
TRACE( "captured %u frames\n", num_entries );
- return num_entries;
+ return i ? i - 1 : 0;
}
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 6af68317732..6f3b08b5ea6 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -28,6 +28,7 @@
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
+#include "ddk/ntddk.h"
#include "ddk/wdm.h"
#include "excpt.h"
#include "wine/test.h"
@@ -9113,6 +9114,87 @@ static void test_copy_context(void)
}
#endif
+static void test_walk_stack(void)
+{
+ ULONG count, expected, frame_count, requested_count, skip_count;
+ void *addrs[256], *addrs2[256];
+ void *start, *end;
+ unsigned int i, j;
+
+ memset(addrs, 0xcc, sizeof(addrs));
+ memset(addrs2, 0xcc, sizeof(addrs2));
+
+ frame_count = RtlCaptureStackBackTrace(0, ARRAY_SIZE(addrs), addrs, NULL);
+ count = RtlWalkFrameChain(addrs2, ARRAY_SIZE(addrs2), 0);
+
+ trace("frame_count %u.\n", frame_count);
+
+ ok(frame_count > 1, "Got zero frame_count.\n");
+ ok(count == frame_count, "Got unexpected frame_count %u, count %u.\n", frame_count, count);
+
+ start = test_walk_stack;
+ end = (BYTE *)start + 0x1000;
+ todo_wine_if(sizeof(void *) == 4)
+ ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
+ start, end, addrs[0]);
+ todo_wine_if(sizeof(void *) == 4)
+ ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
+ start, end, addrs2[0]);
+
+ for (i = 1; i < frame_count; ++i)
+ {
+ ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]);
+ }
+ todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n");
+
+ for (requested_count = frame_count - 1; requested_count <= frame_count + 1; ++requested_count)
+ {
+ for (i = 0; i < 32; ++i)
+ {
+ winetest_push_context("requested_count %u, i %u", requested_count, i);
+ skip_count = (1 << i) >> 8;
+
+ if (i < RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT
+ || i >= RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT + 8)
+ expected = 0;
+ else
+ expected = min(frame_count, requested_count);
+
+ memset(addrs2, 0xcc, sizeof(addrs2));
+ count = RtlWalkFrameChain(addrs2, requested_count, 1 << i);
+ ok(count == expected, "Got unexpected frame_count %u, expected %u.\n", count, expected);
+
+ if (skip_count < count)
+ count -= skip_count;
+ else
+ count = 0;
+
+ for (j = 0; j < count; ++j)
+ ok( addrs2[j] != (void *)(ULONG_PTR)0xcccccccccccccccc, "Address is not set, j %u.\n", j );
+ for (; j < ARRAY_SIZE(addrs2); ++j)
+ ok( addrs2[j] == (void *)(ULONG_PTR)0xcccccccccccccccc, "Address is set, j %u.\n", j );
+
+ if (!count)
+ {
+ winetest_pop_context();
+ continue;
+ }
+
+ memset(addrs, 0xcc, sizeof(addrs));
+ expected = skip_count > frame_count ? 0 : min(frame_count - skip_count, requested_count);
+ count = RtlCaptureStackBackTrace(skip_count, requested_count, addrs, NULL);
+ ok(count == expected, "Got unexpected frame_count %u, expected %u. i %u.\n", count, expected, i);
+
+ count = min(frame_count, requested_count) - skip_count;
+ for (j = 0; j < count; ++j)
+ {
+ ok(addrs[j] == addrs2[j], "Addresses do not match, j %u, %p, %p.\n", j, addrs[j], addrs2[j]);
+ }
+ winetest_pop_context();
+ }
+ }
+}
+
START_TEST(exception)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -9339,5 +9421,6 @@ START_TEST(exception)
test_suspend_thread();
test_suspend_process();
test_unload_trace();
+ test_walk_stack();
VirtualFree(code_mem, 0, MEM_RELEASE);
}
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 0208e2f633f..b94e58ccb26 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1300,7 +1300,7 @@
@ stdcall RtlVerifyVersionInfo(ptr long int64)
@ stdcall -arch=arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr)
@ stub RtlVolumeDeviceToDosName
-@ stub RtlWalkFrameChain
+@ stdcall RtlWalkFrameChain(ptr long long)
@ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
@ stub RtlZeroHeap
@ stdcall RtlZeroMemory(ptr long)
diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h
index 41ad3d721bd..ce558139aa6 100644
--- a/include/ddk/ntddk.h
+++ b/include/ddk/ntddk.h
@@ -245,6 +245,8 @@ typedef EXPAND_STACK_CALLOUT *PEXPAND_STACK_CALLOUT;
typedef GUID UUID;
#endif
+#define RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT 8
+
NTSTATUS WINAPI ExUuidCreate(UUID*);
NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE,PULONG,PCONFIGURATION_TYPE,PULONG,
PCONFIGURATION_TYPE,PULONG,PIO_QUERY_DEVICE_ROUTINE,PVOID);
@@ -267,5 +269,6 @@ NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine(PCREATE_THREAD_NOTIFY_ROUTINE);
NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE);
void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE,PRTL_AVL_COMPARE_ROUTINE,PRTL_AVL_ALLOCATE_ROUTINE, PRTL_AVL_FREE_ROUTINE,void *);
void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE,void *,ULONG,BOOL*);
+ULONG WINAPI RtlWalkFrameChain(void **,ULONG,ULONG);
#endif
diff --git a/include/winnt.h b/include/winnt.h
index ef731e29c52..eb1bd165720 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -1840,6 +1840,8 @@ NTSYSAPI PVOID WINAPI RtlVirtualUnwind(DWORD,ULONG_PTR,ULONG_PTR,RUNTIME_FUNCT
#endif
+NTSYSAPI USHORT WINAPI RtlCaptureStackBackTrace(ULONG,ULONG,void **,ULONG *);
+
/*
* Product types
*/
--
2.31.1
Nov. 3, 2021
[PATCH v5 1/4] ntdll: Factor out capture_stack_back_trace() helper.
by Paul Gofman
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
v5:
- fix max USHORT value.
dlls/ntdll/exception.c | 12 ++++++++++++
dlls/ntdll/ntdll_misc.h | 2 ++
dlls/ntdll/signal_arm.c | 4 ++--
dlls/ntdll/signal_arm64.c | 4 ++--
dlls/ntdll/signal_i386.c | 6 ++++--
dlls/ntdll/signal_x86_64.c | 10 ++++++----
6 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index c3714e8369b..e956d8a722f 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -1065,3 +1065,15 @@ NTSTATUS WINAPI RtlCopyExtendedContext( CONTEXT_EX *dst, ULONG context_flags, CO
memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) );
return STATUS_SUCCESS;
}
+
+
+/*************************************************************************
+ * RtlCaptureStackBackTrace (NTDLL.@)
+ */
+USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
+{
+ ULONG ret;
+
+ ret = capture_stack_back_trace( skip, count, buffer, hash );
+ return min( ret, (USHORT)~0 );
+}
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 34af6b780cf..31a33b04dbf 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -57,6 +57,8 @@ extern void WINAPI KiUserCallbackDispatcher(ULONG,void*,ULONG) DECLSPEC_HIDDEN;
extern RUNTIME_FUNCTION *lookup_function_info( ULONG_PTR pc, ULONG_PTR *base, LDR_DATA_TABLE_ENTRY **module ) DECLSPEC_HIDDEN;
#endif
+extern ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) DECLSPEC_HIDDEN;
+
/* debug helpers */
extern LPCSTR debugstr_us( const UNICODE_STRING *str ) DECLSPEC_HIDDEN;
extern const char *debugstr_exception_code( DWORD code ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
index 0ef210a0331..241ddc3ce70 100644
--- a/dlls/ntdll/signal_arm.c
+++ b/dlls/ntdll/signal_arm.c
@@ -300,9 +300,9 @@ __ASM_STDCALL_FUNC( RtlRaiseException, 4,
"bl " __ASM_NAME("RtlRaiseStatus") )
/*************************************************************************
- * RtlCaptureStackBackTrace (NTDLL.@)
+ * capture_stack_back_trace
*/
-USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
+ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
{
FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash );
return 0;
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index 290639b676b..1bffbe7efe9 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -1473,9 +1473,9 @@ __ASM_STDCALL_FUNC( RtlRaiseException, 4,
"bl " __ASM_NAME("RtlRaiseStatus") /* does not return */ );
/*************************************************************************
- * RtlCaptureStackBackTrace (NTDLL.@)
+ * capture_stack_back_trace
*/
-USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
+ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
{
FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash );
return 0;
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 14971032ce6..26150ce877b 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -481,14 +481,16 @@ __ASM_STDCALL_FUNC( RtlRaiseException, 4,
/*************************************************************************
- * RtlCaptureStackBackTrace (NTDLL.@)
+ * capture_stack_back_trace
*/
-USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
+ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
{
CONTEXT context;
ULONG i;
ULONG *frame;
+ ++skip;
+
RtlCaptureContext( &context );
if (hash) *hash = 0;
frame = (ULONG *)context.Ebp;
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index ef32eba68b7..5f3c8f70208 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1490,19 +1490,21 @@ static inline ULONG hash_pointers( void **ptrs, ULONG count )
/*************************************************************************
- * RtlCaptureStackBackTrace (NTDLL.@)
+ * capture_stack_back_trace
*/
-USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
+ULONG WINAPI capture_stack_back_trace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
{
UNWIND_HISTORY_TABLE table;
DISPATCHER_CONTEXT dispatch;
CONTEXT context;
NTSTATUS status;
ULONG i;
- USHORT num_entries = 0;
+ ULONG num_entries = 0;
TRACE( "(%u, %u, %p, %p)\n", skip, count, buffer, hash );
+ ++skip;
+
RtlCaptureContext( &context );
dispatch.TargetIp = 0;
dispatch.ContextRecord = &context;
@@ -1529,7 +1531,7 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
if (i >= skip) buffer[num_entries++] = (void *)context.Rip;
}
if (hash && num_entries > 0) *hash = hash_pointers( buffer, num_entries );
- TRACE( "captured %hu frames\n", num_entries );
+ TRACE( "captured %u frames\n", num_entries );
return num_entries;
}
--
2.31.1
Nov. 3, 2021