2020-09-30 21:01:18 -05:00
|
|
|
/*
|
2024-10-05 07:46:00 -05:00
|
|
|
* Copyright 2020-2024 Elizabeth Figura for CodeWeavers
|
2020-09-30 21:01:18 -05:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This application contains code derived from piglit, the license for which
|
|
|
|
* follows:
|
|
|
|
*
|
|
|
|
* Copyright © 2010 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2022-01-26 19:40:28 -06:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
# define _HRESULT_DEFINED
|
|
|
|
typedef int HRESULT;
|
2024-04-18 20:05:16 +02:00
|
|
|
#else
|
|
|
|
# define WIDL_C_INLINE_WRAPPERS
|
2022-01-26 19:40:28 -06:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
#define CONST_VTABLE
|
|
|
|
#include "config.h"
|
|
|
|
#include <ctype.h>
|
2020-09-30 21:01:18 -05:00
|
|
|
#include <errno.h>
|
2022-01-26 19:40:28 -06:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
2022-03-21 20:42:16 -05:00
|
|
|
#include <string.h>
|
2022-01-26 19:40:28 -06:00
|
|
|
#include "vkd3d_windows.h"
|
|
|
|
#include "vkd3d_d3dcommon.h"
|
|
|
|
#include "vkd3d_d3dcompiler.h"
|
|
|
|
#include "vkd3d_test.h"
|
|
|
|
#include "shader_runner.h"
|
2020-09-30 21:01:18 -05:00
|
|
|
|
2023-02-21 17:46:36 -06:00
|
|
|
struct test_options test_options = {0};
|
|
|
|
|
2024-02-19 17:01:00 +01:00
|
|
|
#ifdef VKD3D_CROSSTEST
|
|
|
|
static const char HLSL_COMPILER[] = "d3dcompiler47.dll";
|
|
|
|
#else
|
|
|
|
static const char HLSL_COMPILER[] = "vkd3d-shader";
|
|
|
|
#endif
|
|
|
|
static const char *const model_strings[] =
|
|
|
|
{
|
|
|
|
[SHADER_MODEL_2_0] = "2.0",
|
|
|
|
[SHADER_MODEL_3_0] = "3.0",
|
|
|
|
[SHADER_MODEL_4_0] = "4.0",
|
|
|
|
[SHADER_MODEL_4_1] = "4.1",
|
|
|
|
[SHADER_MODEL_5_0] = "5.0",
|
|
|
|
[SHADER_MODEL_5_1] = "5.1",
|
|
|
|
[SHADER_MODEL_6_0] = "6.0",
|
|
|
|
};
|
|
|
|
|
2022-03-12 15:02:15 -06:00
|
|
|
void fatal_error(const char *format, ...)
|
2021-11-05 19:35:50 +01:00
|
|
|
{
|
2024-10-20 17:58:37 +02:00
|
|
|
unsigned int i;
|
2021-11-05 19:35:50 +01:00
|
|
|
va_list args;
|
|
|
|
|
2024-10-20 17:58:37 +02:00
|
|
|
for (i = 0; i < vkd3d_test_state.context_count; ++i)
|
|
|
|
fprintf(stderr, "%s: ", vkd3d_test_state.context[i]);
|
|
|
|
|
2021-11-05 19:35:50 +01:00
|
|
|
va_start(args, format);
|
|
|
|
vfprintf(stderr, format, args);
|
|
|
|
va_end(args);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2020-09-30 21:01:18 -05:00
|
|
|
enum parse_state
|
|
|
|
{
|
|
|
|
STATE_NONE,
|
2022-03-21 20:42:16 -05:00
|
|
|
STATE_INPUT_LAYOUT,
|
2020-11-21 17:23:45 -06:00
|
|
|
STATE_PREPROC,
|
2020-11-24 00:29:57 -06:00
|
|
|
STATE_PREPROC_INVALID,
|
2022-01-26 15:35:33 +01:00
|
|
|
STATE_REQUIRE,
|
2022-06-08 18:18:35 -05:00
|
|
|
STATE_RESOURCE,
|
2021-11-05 19:35:49 +01:00
|
|
|
STATE_SAMPLER,
|
2024-12-01 12:54:04 -06:00
|
|
|
STATE_SHADER,
|
2020-09-30 21:01:18 -05:00
|
|
|
STATE_TEST,
|
|
|
|
};
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
static enum shader_model match_shader_model_string(const char *string, const char **rest)
|
|
|
|
{
|
|
|
|
for (enum shader_model i = 0; i < ARRAY_SIZE(model_strings); ++i)
|
|
|
|
{
|
|
|
|
if (!strncmp(string, model_strings[i], strlen(model_strings[i])))
|
|
|
|
{
|
|
|
|
*rest = string + strlen(model_strings[i]);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
/* Allow e.g. "4" as a shorthand for "4.0". */
|
|
|
|
if (string[0] == model_strings[i][0] && !strcmp(&model_strings[i][1], ".0")
|
|
|
|
&& string[1] != '.' && !isdigit(string[1]))
|
|
|
|
{
|
|
|
|
*rest = string + 1;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fatal_error("Unrecognized shader model '%s'.\n", string);
|
|
|
|
}
|
|
|
|
|
2024-03-19 12:36:23 +01:00
|
|
|
static bool match_tag(struct shader_runner *runner, const char *tag)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < runner->caps->tag_count; ++i)
|
|
|
|
{
|
|
|
|
if (!strcmp(tag, runner->caps->tags[i]))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
static bool check_qualifier_args_conjunction(struct shader_runner *runner,
|
|
|
|
const char *line, const char **const rest, uint32_t *model_mask)
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2025-01-16 14:27:57 -05:00
|
|
|
static const char *const valid_tags[] =
|
|
|
|
{
|
|
|
|
"d3d12",
|
|
|
|
"glsl",
|
|
|
|
"llvmpipe",
|
|
|
|
"mesa<23.3",
|
|
|
|
"msl",
|
|
|
|
"mvk",
|
|
|
|
"opengl",
|
|
|
|
"vulkan",
|
|
|
|
};
|
2023-11-10 18:37:40 -03:00
|
|
|
bool holds = true;
|
2020-09-30 21:01:18 -05:00
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
*model_mask = ~0u;
|
2022-03-21 20:42:16 -05:00
|
|
|
|
2023-11-10 18:37:40 -03:00
|
|
|
while (*line != ')' && *line != '|')
|
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
enum shader_model model;
|
2023-11-10 18:37:40 -03:00
|
|
|
bool match = false;
|
|
|
|
|
|
|
|
while (isspace(*line))
|
|
|
|
++line;
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
if (!strncmp(line, "sm>=", 4))
|
2023-11-10 18:37:40 -03:00
|
|
|
{
|
2024-03-19 12:36:23 +01:00
|
|
|
match = true;
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
line += 4;
|
|
|
|
model = match_shader_model_string(line, &line);
|
|
|
|
*model_mask &= ~((1u << model) - 1);
|
|
|
|
if (runner->minimum_shader_model < model)
|
2024-03-19 12:36:23 +01:00
|
|
|
holds = false;
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
}
|
|
|
|
else if (!strncmp(line, "sm<", 3))
|
|
|
|
{
|
|
|
|
match = true;
|
|
|
|
line += 3;
|
|
|
|
model = match_shader_model_string(line, &line);
|
|
|
|
*model_mask &= ((1u << model) - 1);
|
|
|
|
if (runner->minimum_shader_model >= model)
|
|
|
|
holds = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (unsigned int i = 0; i < ARRAY_SIZE(valid_tags); ++i)
|
|
|
|
{
|
|
|
|
const char *option_text = valid_tags[i];
|
|
|
|
size_t option_len = strlen(option_text);
|
|
|
|
|
|
|
|
if (strncmp(line, option_text, option_len))
|
|
|
|
continue;
|
2024-03-19 12:36:23 +01:00
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
match = true;
|
|
|
|
line += option_len;
|
|
|
|
holds &= match_tag(runner, option_text);
|
|
|
|
break;
|
|
|
|
}
|
2023-11-10 18:37:40 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
while (isspace(*line))
|
|
|
|
++line;
|
|
|
|
|
|
|
|
if (match && *line == '&')
|
|
|
|
{
|
|
|
|
++line;
|
|
|
|
}
|
|
|
|
else if (*line != ')' && *line != '|')
|
|
|
|
{
|
|
|
|
fatal_error("Invalid qualifier argument '%s'.\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(*line == ')' || *line == '|');
|
2020-09-30 21:01:18 -05:00
|
|
|
if (rest)
|
2023-11-10 18:37:40 -03:00
|
|
|
*rest = line;
|
|
|
|
|
|
|
|
return holds;
|
|
|
|
}
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
static bool check_qualifier_args(struct shader_runner *runner,
|
|
|
|
const char *line, const char **const rest, uint32_t *model_mask)
|
2023-11-10 18:37:40 -03:00
|
|
|
{
|
|
|
|
bool first = true;
|
|
|
|
bool holds = false;
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
if (*line != '(')
|
|
|
|
{
|
|
|
|
*model_mask = ~0u;
|
|
|
|
return true;
|
|
|
|
}
|
2023-11-10 18:37:40 -03:00
|
|
|
++line;
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
*model_mask = 0;
|
|
|
|
|
2023-11-10 18:37:40 -03:00
|
|
|
while (*line != ')')
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
uint32_t sub_mask;
|
|
|
|
|
2023-11-10 18:37:40 -03:00
|
|
|
if (!first && *line == '|')
|
|
|
|
++line;
|
|
|
|
first = false;
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
holds = check_qualifier_args_conjunction(runner, line, &line, &sub_mask) || holds;
|
|
|
|
*model_mask |= sub_mask;
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
2023-11-10 18:37:40 -03:00
|
|
|
|
|
|
|
assert(*line == ')');
|
|
|
|
if (rest)
|
|
|
|
*rest = line + 1;
|
|
|
|
|
|
|
|
return holds;
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
|
|
|
|
2024-12-10 18:10:59 -06:00
|
|
|
static bool match_string_generic(struct shader_runner *runner, const char *line,
|
|
|
|
const char *token, const char **const rest, bool allow_qualifier_args)
|
2023-09-14 19:18:58 +10:00
|
|
|
{
|
|
|
|
size_t len = strlen(token);
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
uint32_t model_mask;
|
2023-11-10 18:37:40 -03:00
|
|
|
bool holds = true;
|
2023-09-14 19:18:58 +10:00
|
|
|
|
2024-12-10 18:10:59 -06:00
|
|
|
while (isspace(*line))
|
2023-09-14 19:18:58 +10:00
|
|
|
++line;
|
|
|
|
|
2024-12-10 18:10:59 -06:00
|
|
|
if (strncmp(line, token, len) || !(isspace(line[len]) || line[len] == '(' || line[len] == ']'))
|
2023-09-14 19:18:58 +10:00
|
|
|
return false;
|
2023-11-10 18:37:40 -03:00
|
|
|
line += len;
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
if (allow_qualifier_args)
|
|
|
|
holds = check_qualifier_args(runner, line, &line, &model_mask);
|
2023-11-10 18:37:40 -03:00
|
|
|
|
2023-09-14 19:18:58 +10:00
|
|
|
if (rest)
|
|
|
|
{
|
2023-11-10 18:37:40 -03:00
|
|
|
*rest = line;
|
2023-09-14 19:18:58 +10:00
|
|
|
while (isspace(**rest))
|
|
|
|
++*rest;
|
|
|
|
}
|
2023-11-10 18:37:40 -03:00
|
|
|
return holds;
|
|
|
|
}
|
|
|
|
|
2024-03-19 12:36:23 +01:00
|
|
|
static bool match_string_with_args(struct shader_runner *runner,
|
|
|
|
const char *line, const char *token, const char **const rest)
|
2023-11-10 18:37:40 -03:00
|
|
|
{
|
2024-12-10 18:10:59 -06:00
|
|
|
return match_string_generic(runner, line, token, rest, true);
|
2023-11-10 18:37:40 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool match_string(const char *line, const char *token, const char **const rest)
|
|
|
|
{
|
2024-12-10 18:10:59 -06:00
|
|
|
return match_string_generic(NULL, line, token, rest, false);
|
2023-09-14 19:18:58 +10:00
|
|
|
}
|
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
static const char *close_parentheses(const char *line)
|
|
|
|
{
|
|
|
|
while (isspace(*line))
|
|
|
|
++line;
|
|
|
|
|
|
|
|
if (*line != ')')
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
2024-08-01 19:37:37 -04:00
|
|
|
static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_type, unsigned int *texel_size,
|
|
|
|
bool *is_shadow, const char **rest)
|
|
|
|
{
|
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
const char *string;
|
|
|
|
enum texture_data_type data_type;
|
|
|
|
unsigned int texel_size;
|
|
|
|
DXGI_FORMAT format;
|
|
|
|
bool is_shadow;
|
|
|
|
}
|
|
|
|
formats[] =
|
|
|
|
{
|
2024-08-01 21:03:46 -04:00
|
|
|
{"r32g32b32a32-float", TEXTURE_DATA_FLOAT, 16, DXGI_FORMAT_R32G32B32A32_FLOAT},
|
|
|
|
{"r32g32b32a32-sint", TEXTURE_DATA_SINT, 16, DXGI_FORMAT_R32G32B32A32_SINT},
|
|
|
|
{"r32g32b32a32-uint", TEXTURE_DATA_UINT, 16, DXGI_FORMAT_R32G32B32A32_UINT},
|
|
|
|
{"r32g32-float", TEXTURE_DATA_FLOAT, 8, DXGI_FORMAT_R32G32_FLOAT},
|
|
|
|
{"r32g32-sint", TEXTURE_DATA_SINT, 8, DXGI_FORMAT_R32G32_SINT},
|
|
|
|
{"r32g32-uint", TEXTURE_DATA_UINT, 8, DXGI_FORMAT_R32G32_UINT},
|
|
|
|
{"r32-float-shadow", TEXTURE_DATA_FLOAT, 4, DXGI_FORMAT_R32_FLOAT, true},
|
|
|
|
{"r32-float", TEXTURE_DATA_FLOAT, 4, DXGI_FORMAT_R32_FLOAT},
|
|
|
|
{"r32-sint", TEXTURE_DATA_SINT, 4, DXGI_FORMAT_R32_SINT},
|
|
|
|
{"r32-uint", TEXTURE_DATA_UINT, 4, DXGI_FORMAT_R32_UINT},
|
|
|
|
{"r32-typeless", TEXTURE_DATA_UINT, 4, DXGI_FORMAT_R32_TYPELESS},
|
2024-08-01 19:13:31 -04:00
|
|
|
{"unknown", TEXTURE_DATA_UINT, 0, DXGI_FORMAT_UNKNOWN},
|
2024-08-01 19:37:37 -04:00
|
|
|
};
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(formats); ++i)
|
|
|
|
{
|
|
|
|
if (match_string(line, formats[i].string, rest))
|
|
|
|
{
|
|
|
|
if (data_type)
|
|
|
|
*data_type = formats[i].data_type;
|
2024-08-01 19:13:31 -04:00
|
|
|
if (texel_size)
|
|
|
|
*texel_size = formats[i].texel_size;
|
2024-08-01 19:37:37 -04:00
|
|
|
if (is_shadow)
|
|
|
|
*is_shadow = formats[i].is_shadow;
|
|
|
|
return formats[i].format;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fatal_error("Unknown format '%s'.\n", line);
|
|
|
|
}
|
|
|
|
|
2024-10-05 07:46:00 -05:00
|
|
|
static const char *const shader_cap_strings[] =
|
|
|
|
{
|
|
|
|
[SHADER_CAP_CLIP_PLANES] = "clip-planes",
|
|
|
|
[SHADER_CAP_DEPTH_BOUNDS] = "depth-bounds",
|
|
|
|
[SHADER_CAP_FLOAT64] = "float64",
|
2024-10-05 10:26:20 -05:00
|
|
|
[SHADER_CAP_FOG] = "fog",
|
2024-10-05 07:46:00 -05:00
|
|
|
[SHADER_CAP_GEOMETRY_SHADER] = "geometry-shader",
|
|
|
|
[SHADER_CAP_INT64] = "int64",
|
|
|
|
[SHADER_CAP_POINT_SIZE] = "point-size",
|
|
|
|
[SHADER_CAP_ROV] = "rov",
|
|
|
|
[SHADER_CAP_WAVE_OPS] = "wave-ops",
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool match_shader_cap_string(const char *line, enum shader_cap *cap)
|
|
|
|
{
|
|
|
|
for (enum shader_cap i = 0; i < SHADER_CAP_COUNT; ++i)
|
|
|
|
{
|
|
|
|
if (match_string(line, shader_cap_strings[i], &line))
|
|
|
|
{
|
|
|
|
*cap = i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-19 12:35:31 -05:00
|
|
|
static void parse_require_directive(struct shader_runner *runner, const char *line)
|
2022-01-26 15:35:33 +01:00
|
|
|
{
|
2024-10-05 07:46:00 -05:00
|
|
|
enum shader_cap shader_cap;
|
2023-09-14 19:29:24 +10:00
|
|
|
bool less_than = false;
|
2023-07-13 07:41:14 +02:00
|
|
|
unsigned int i;
|
|
|
|
|
2023-09-14 19:29:24 +10:00
|
|
|
if (match_string(line, "shader model >=", &line)
|
|
|
|
|| (less_than = match_string(line, "shader model <", &line)))
|
2022-01-26 15:35:33 +01:00
|
|
|
{
|
|
|
|
for (i = 0; i < ARRAY_SIZE(model_strings); ++i)
|
|
|
|
{
|
|
|
|
if (match_string(line, model_strings[i], &line))
|
|
|
|
{
|
2023-09-14 19:29:24 +10:00
|
|
|
if (less_than)
|
|
|
|
{
|
|
|
|
if (!i)
|
|
|
|
fatal_error("Shader model < '%s' is invalid.\n", line);
|
|
|
|
runner->maximum_shader_model = min(runner->maximum_shader_model, i - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
runner->minimum_shader_model = max(runner->minimum_shader_model, i);
|
|
|
|
}
|
2022-01-26 15:35:33 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fatal_error("Unknown shader model '%s'.\n", line);
|
|
|
|
}
|
2023-07-13 07:41:14 +02:00
|
|
|
else if (match_string(line, "options:", &line))
|
|
|
|
{
|
|
|
|
static const struct option
|
|
|
|
{
|
|
|
|
unsigned int option;
|
|
|
|
const char *name;
|
|
|
|
}
|
|
|
|
options[] =
|
|
|
|
{
|
|
|
|
{ 0, "none" },
|
|
|
|
{ D3DCOMPILE_PACK_MATRIX_ROW_MAJOR, "row-major" },
|
|
|
|
{ D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR, "column-major" },
|
2023-08-25 15:05:51 +02:00
|
|
|
{ D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY, "backcompat" },
|
2024-01-26 16:32:30 -06:00
|
|
|
{ D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES, "unbounded-descriptor-arrays" },
|
2023-07-13 07:41:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
runner->compile_options = 0;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(options); ++i)
|
|
|
|
{
|
|
|
|
if (match_string(line, options[i].name, &line))
|
|
|
|
runner->compile_options |= options[i].option;
|
|
|
|
}
|
|
|
|
}
|
2024-08-01 19:13:31 -04:00
|
|
|
else if (match_string(line, "format", &line))
|
|
|
|
{
|
|
|
|
DXGI_FORMAT format = parse_format(line, NULL, NULL, NULL, &line);
|
|
|
|
|
|
|
|
while (line[0] != '\0')
|
|
|
|
{
|
|
|
|
if (match_string(line, "uav-load", &line))
|
|
|
|
runner->require_format_caps[format] |= FORMAT_CAP_UAV_LOAD;
|
|
|
|
else
|
|
|
|
fatal_error("Unknown format cap '%s'.\n", line);
|
|
|
|
}
|
|
|
|
}
|
2024-10-05 07:46:00 -05:00
|
|
|
else if (match_shader_cap_string(line, &shader_cap))
|
2023-11-23 13:17:54 +10:00
|
|
|
{
|
2024-10-05 07:46:00 -05:00
|
|
|
runner->require_shader_caps[shader_cap] = true;
|
2024-10-03 16:23:04 -05:00
|
|
|
}
|
2022-01-26 15:35:33 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fatal_error("Unknown require directive '%s'.\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-17 19:53:12 -05:00
|
|
|
static D3D12_COMPARISON_FUNC parse_comparison_func(const char *line, const char **rest)
|
2024-04-15 10:33:15 +10:00
|
|
|
{
|
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
const char *string;
|
|
|
|
D3D12_COMPARISON_FUNC func;
|
|
|
|
}
|
|
|
|
funcs[] =
|
|
|
|
{
|
|
|
|
{"less equal", D3D12_COMPARISON_FUNC_LESS_EQUAL},
|
|
|
|
{"not equal", D3D12_COMPARISON_FUNC_NOT_EQUAL},
|
|
|
|
{"greater equal", D3D12_COMPARISON_FUNC_GREATER_EQUAL},
|
|
|
|
{"never", D3D12_COMPARISON_FUNC_NEVER},
|
|
|
|
{"less", D3D12_COMPARISON_FUNC_LESS},
|
|
|
|
{"equal", D3D12_COMPARISON_FUNC_EQUAL},
|
|
|
|
{"greater", D3D12_COMPARISON_FUNC_GREATER},
|
|
|
|
{"always", D3D12_COMPARISON_FUNC_ALWAYS},
|
|
|
|
};
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(funcs); ++i)
|
|
|
|
{
|
2024-05-17 19:53:12 -05:00
|
|
|
if (match_string(line, funcs[i].string, rest))
|
2024-04-15 10:33:15 +10:00
|
|
|
return funcs[i].func;
|
|
|
|
}
|
|
|
|
|
|
|
|
fatal_error("Unknown comparison func '%s'.\n", line);
|
|
|
|
}
|
|
|
|
|
2021-11-05 19:35:49 +01:00
|
|
|
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;
|
2021-11-05 19:35:50 +01:00
|
|
|
|
|
|
|
fatal_error("Unknown sampler address mode '%s'.\n", line);
|
2021-11-05 19:35:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void parse_sampler_directive(struct sampler *sampler, const char *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;
|
2024-02-23 12:30:16 +10:00
|
|
|
if (sampler->func)
|
|
|
|
sampler->filter |= D3D12_FILTER_REDUCTION_TYPE_COMPARISON << D3D12_FILTER_REDUCTION_TYPE_SHIFT;
|
2021-11-05 19:35:50 +01:00
|
|
|
return;
|
2021-11-05 19:35:49 +01:00
|
|
|
}
|
|
|
|
}
|
2021-11-05 19:35:50 +01:00
|
|
|
|
|
|
|
fatal_error("Unknown sampler filter '%s'.\n", line);
|
2021-11-05 19:35:49 +01:00
|
|
|
}
|
2024-02-23 12:30:16 +10:00
|
|
|
else if (match_string(line, "comparison", &line))
|
|
|
|
{
|
2024-04-15 10:33:15 +10:00
|
|
|
sampler->filter |= D3D12_FILTER_REDUCTION_TYPE_COMPARISON << D3D12_FILTER_REDUCTION_TYPE_SHIFT;
|
2024-05-17 19:53:12 -05:00
|
|
|
sampler->func = parse_comparison_func(line, &line);
|
2024-04-15 10:33:15 +10:00
|
|
|
return;
|
2024-02-23 12:30:16 +10:00
|
|
|
}
|
2021-11-05 19:35:49 +01:00
|
|
|
else
|
|
|
|
{
|
2021-11-05 19:35:50 +01:00
|
|
|
fatal_error("Unknown sampler directive '%s'.\n", line);
|
2021-11-05 19:35:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 20:42:17 -05:00
|
|
|
static void parse_resource_directive(struct resource_params *resource, const char *line)
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2021-10-03 19:19:09 -05:00
|
|
|
if (match_string(line, "format", &line))
|
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.format = parse_format(line, &resource->data_type,
|
|
|
|
&resource->desc.texel_size, &resource->is_shadow, &line);
|
2024-07-31 21:48:19 -04:00
|
|
|
assert_that(!resource->explicit_format, "Resource format already specified.\n");
|
|
|
|
resource->explicit_format = true;
|
2021-10-03 19:19:09 -05:00
|
|
|
}
|
2024-02-01 16:01:45 +10:00
|
|
|
else if (match_string(line, "stride", &line))
|
|
|
|
{
|
|
|
|
if (sscanf(line, "%u", &resource->stride) < 1)
|
|
|
|
fatal_error("Malformed texture stride '%s'.\n", line);
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.texel_size = resource->stride;
|
|
|
|
resource->desc.format = DXGI_FORMAT_UNKNOWN;
|
2024-07-31 21:48:19 -04:00
|
|
|
assert_that(!resource->explicit_format, "Resource format already specified.\n");
|
|
|
|
resource->explicit_format = true;
|
2024-02-01 16:01:45 +10:00
|
|
|
}
|
2021-10-03 19:19:09 -05:00
|
|
|
else if (match_string(line, "size", &line))
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
if (sscanf(line, "( buffer , %u ) ", &resource->desc.width) == 1)
|
2024-01-24 16:11:17 -03:00
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.dimension = RESOURCE_DIMENSION_BUFFER;
|
|
|
|
resource->desc.height = 1;
|
2024-01-24 16:11:17 -03:00
|
|
|
}
|
2024-06-17 16:01:04 -05:00
|
|
|
else if (sscanf(line, "( raw_buffer , %u ) ", &resource->desc.width) == 1)
|
2024-05-31 23:46:38 +10:00
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.dimension = RESOURCE_DIMENSION_BUFFER;
|
|
|
|
resource->desc.height = 1;
|
2024-05-31 23:46:38 +10:00
|
|
|
resource->is_raw = true;
|
|
|
|
}
|
2024-06-17 16:01:04 -05:00
|
|
|
else if (sscanf(line, "( counter_buffer , %u ) ", &resource->desc.width) == 1)
|
2024-03-13 16:36:59 +10:00
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.dimension = RESOURCE_DIMENSION_BUFFER;
|
|
|
|
resource->desc.height = 1;
|
2024-03-13 16:36:59 +10:00
|
|
|
resource->is_uav_counter = true;
|
|
|
|
resource->stride = sizeof(uint32_t);
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.texel_size = resource->stride;
|
|
|
|
resource->desc.format = DXGI_FORMAT_UNKNOWN;
|
2024-07-31 21:48:19 -04:00
|
|
|
assert_that(!resource->explicit_format, "Resource format already specified.\n");
|
|
|
|
resource->explicit_format = true;
|
2024-03-13 16:36:59 +10:00
|
|
|
}
|
2024-06-17 16:01:04 -05:00
|
|
|
else if (sscanf(line, "( 2d , %u , %u ) ", &resource->desc.width, &resource->desc.height) == 2)
|
2024-01-24 16:11:17 -03:00
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.dimension = RESOURCE_DIMENSION_2D;
|
2024-01-24 16:11:17 -03:00
|
|
|
}
|
2024-06-17 16:01:04 -05:00
|
|
|
else if (sscanf(line, "( 2dms , %u , %u , %u ) ",
|
|
|
|
&resource->desc.sample_count, &resource->desc.width, &resource->desc.height) == 3)
|
2024-04-10 13:51:06 +10:00
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.dimension = RESOURCE_DIMENSION_2D;
|
2024-04-10 13:51:06 +10:00
|
|
|
}
|
2024-01-24 16:11:17 -03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fatal_error("Malformed resource size '%s'.\n", line);
|
|
|
|
}
|
2021-10-03 19:19:08 -05:00
|
|
|
}
|
2023-04-30 19:23:00 -05:00
|
|
|
else if (match_string(line, "levels", &line))
|
|
|
|
{
|
|
|
|
char *rest;
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc.level_count = strtoul(line, &rest, 10);
|
2023-04-30 19:23:00 -05:00
|
|
|
if (rest == line)
|
|
|
|
fatal_error("Malformed texture directive '%s'.\n", line);
|
|
|
|
}
|
2021-10-03 19:19:08 -05:00
|
|
|
else
|
|
|
|
{
|
2021-10-03 19:19:09 -05:00
|
|
|
union
|
|
|
|
{
|
|
|
|
float f;
|
|
|
|
int32_t i;
|
|
|
|
uint32_t u;
|
|
|
|
} u;
|
2021-10-03 19:19:08 -05:00
|
|
|
char *rest;
|
|
|
|
|
2021-10-03 19:19:09 -05:00
|
|
|
u.u = 0;
|
|
|
|
|
|
|
|
for (;;)
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2022-03-21 20:42:17 -05:00
|
|
|
switch (resource->data_type)
|
2021-10-03 19:19:09 -05:00
|
|
|
{
|
|
|
|
case TEXTURE_DATA_FLOAT:
|
|
|
|
u.f = strtof(line, &rest);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_DATA_SINT:
|
2023-04-20 19:46:27 -05:00
|
|
|
u.i = strtol(line, &rest, 0);
|
2021-10-03 19:19:09 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_DATA_UINT:
|
2023-04-20 19:46:27 -05:00
|
|
|
u.u = strtoul(line, &rest, 0);
|
2021-10-03 19:19:09 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rest == line)
|
|
|
|
break;
|
|
|
|
|
2022-03-21 20:42:17 -05:00
|
|
|
vkd3d_array_reserve((void **)&resource->data, &resource->data_capacity, resource->data_size + sizeof(u), 1);
|
|
|
|
memcpy(resource->data + resource->data_size, &u, sizeof(u));
|
|
|
|
resource->data_size += sizeof(u);
|
2021-10-03 19:19:08 -05:00
|
|
|
line = rest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 20:42:16 -05:00
|
|
|
static void parse_input_layout_directive(struct shader_runner *runner, const char *line)
|
|
|
|
{
|
|
|
|
struct input_element *element;
|
|
|
|
const char *rest;
|
|
|
|
|
|
|
|
vkd3d_array_reserve((void **)&runner->input_elements, &runner->input_element_capacity,
|
|
|
|
runner->input_element_count + 1, sizeof(*runner->input_elements));
|
|
|
|
element = &runner->input_elements[runner->input_element_count++];
|
|
|
|
|
|
|
|
element->slot = strtoul(line, (char **)&rest, 10);
|
|
|
|
if (rest == line)
|
|
|
|
fatal_error("Malformed input layout directive '%s'.\n", line);
|
|
|
|
line = rest;
|
|
|
|
|
2024-02-23 12:30:16 +10:00
|
|
|
element->format = parse_format(line, NULL, &element->texel_size, NULL, &line);
|
2022-03-21 20:42:16 -05:00
|
|
|
|
|
|
|
if (!(rest = strpbrk(line, " \n")))
|
|
|
|
rest = line + strlen(line);
|
|
|
|
element->name = malloc(rest - line + 1);
|
|
|
|
memcpy(element->name, line, rest - line);
|
|
|
|
element->name[rest - line] = 0;
|
|
|
|
line = rest;
|
|
|
|
|
|
|
|
element->index = strtoul(line, (char **)&rest, 10);
|
|
|
|
if (rest == line)
|
|
|
|
element->index = 0;
|
|
|
|
}
|
|
|
|
|
2022-06-08 18:18:35 -05:00
|
|
|
void init_resource(struct resource *resource, const struct resource_params *params)
|
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
resource->desc = params->desc;
|
2022-06-08 18:18:37 -05:00
|
|
|
}
|
|
|
|
|
2023-09-22 07:31:31 +02:00
|
|
|
struct resource *shader_runner_get_resource(struct shader_runner *runner, enum resource_type type, unsigned int slot)
|
2022-06-08 18:18:37 -05:00
|
|
|
{
|
|
|
|
struct resource *resource;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < runner->resource_count; ++i)
|
|
|
|
{
|
|
|
|
resource = runner->resources[i];
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
if (resource->desc.type == type && resource->desc.slot == slot)
|
2022-06-08 18:18:37 -05:00
|
|
|
return resource;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2022-06-08 18:18:35 -05:00
|
|
|
}
|
|
|
|
|
2024-04-10 13:51:06 +10:00
|
|
|
static void set_resource(struct shader_runner *runner, const struct resource_params *params)
|
2022-04-07 18:58:13 -05:00
|
|
|
{
|
2024-04-10 13:51:06 +10:00
|
|
|
struct resource *resource;
|
2022-04-07 18:58:13 -05:00
|
|
|
size_t i;
|
|
|
|
|
2024-04-10 13:51:06 +10:00
|
|
|
if (!(resource = runner->ops->create_resource(runner, params)))
|
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
if (!bitmap_is_set(runner->failed_resources[params->desc.type], params->desc.slot))
|
2024-04-10 13:51:06 +10:00
|
|
|
{
|
|
|
|
++runner->failed_resource_count;
|
2024-06-17 16:01:04 -05:00
|
|
|
bitmap_set(runner->failed_resources[params->desc.type], params->desc.slot);
|
2024-04-10 13:51:06 +10:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
if (bitmap_is_set(runner->failed_resources[params->desc.type], params->desc.slot))
|
2024-04-10 13:51:06 +10:00
|
|
|
{
|
|
|
|
assert(runner->failed_resource_count);
|
|
|
|
--runner->failed_resource_count;
|
2024-06-17 16:01:04 -05:00
|
|
|
bitmap_clear(runner->failed_resources[params->desc.type], params->desc.slot);
|
2024-04-10 13:51:06 +10:00
|
|
|
}
|
|
|
|
|
2022-04-07 18:58:13 -05:00
|
|
|
for (i = 0; i < runner->resource_count; ++i)
|
|
|
|
{
|
2024-06-17 16:01:04 -05:00
|
|
|
if (runner->resources[i]->desc.slot == resource->desc.slot
|
|
|
|
&& runner->resources[i]->desc.type == resource->desc.type)
|
2022-04-07 18:58:13 -05:00
|
|
|
{
|
|
|
|
runner->ops->destroy_resource(runner, runner->resources[i]);
|
|
|
|
runner->resources[i] = resource;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-11 12:18:29 -05:00
|
|
|
if (runner->resource_count == MAX_RESOURCES)
|
|
|
|
fatal_error("Too many resources declared.\n");
|
|
|
|
|
2022-04-07 18:58:13 -05:00
|
|
|
runner->resources[runner->resource_count++] = resource;
|
|
|
|
}
|
|
|
|
|
2024-05-17 19:51:56 -05:00
|
|
|
static void set_default_target(struct shader_runner *runner)
|
|
|
|
{
|
|
|
|
struct resource_params params = {0};
|
|
|
|
|
|
|
|
if (shader_runner_get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0)
|
|
|
|
|| shader_runner_get_resource(runner, RESOURCE_TYPE_DEPTH_STENCIL, 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
params.desc.slot = 0;
|
|
|
|
params.desc.type = RESOURCE_TYPE_RENDER_TARGET;
|
|
|
|
params.desc.dimension = RESOURCE_DIMENSION_2D;
|
|
|
|
params.desc.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
|
|
|
params.data_type = TEXTURE_DATA_FLOAT;
|
|
|
|
params.desc.texel_size = 16;
|
|
|
|
params.desc.width = RENDER_TARGET_WIDTH;
|
|
|
|
params.desc.height = RENDER_TARGET_HEIGHT;
|
|
|
|
params.desc.level_count = 1;
|
|
|
|
|
|
|
|
set_resource(runner, ¶ms);
|
|
|
|
}
|
|
|
|
|
2022-03-19 12:35:31 -05:00
|
|
|
static void set_uniforms(struct shader_runner *runner, size_t offset, size_t count, const void *uniforms)
|
2022-01-26 19:40:32 -06:00
|
|
|
{
|
2024-01-31 15:21:23 -03:00
|
|
|
size_t initial_count = runner->uniform_count;
|
|
|
|
|
2022-03-19 12:35:31 -05:00
|
|
|
runner->uniform_count = align(max(runner->uniform_count, offset + count), 4);
|
|
|
|
vkd3d_array_reserve((void **)&runner->uniforms, &runner->uniform_capacity,
|
|
|
|
runner->uniform_count, sizeof(*runner->uniforms));
|
2024-01-31 15:21:23 -03:00
|
|
|
memset(runner->uniforms + initial_count, 127,
|
|
|
|
(runner->uniform_count - initial_count) * sizeof(*runner->uniforms));
|
2022-03-19 12:35:31 -05:00
|
|
|
memcpy(runner->uniforms + offset, uniforms, count * sizeof(*runner->uniforms));
|
2022-01-26 19:40:32 -06:00
|
|
|
}
|
|
|
|
|
2024-02-13 15:08:03 +10:00
|
|
|
static void read_int(const char **line, int *i, bool is_uniform)
|
2023-03-17 12:35:13 +01:00
|
|
|
{
|
|
|
|
char *rest;
|
|
|
|
long val;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
val = strtol(*line, &rest, 0);
|
|
|
|
|
2024-02-13 15:08:03 +10:00
|
|
|
if (errno != 0 || (is_uniform && *rest != '\0' && !isspace((unsigned char)*rest)))
|
2023-03-17 12:35:13 +01:00
|
|
|
fatal_error("Malformed int constant '%s'.\n", *line);
|
|
|
|
|
|
|
|
*i = val;
|
|
|
|
if (*i != val)
|
|
|
|
fatal_error("Out of range int constant '%.*s'.\n", (int)(rest - *line), *line);
|
|
|
|
|
2024-02-13 15:08:03 +10:00
|
|
|
*line = rest + (!is_uniform && *rest == ',');
|
2023-03-17 12:35:13 +01:00
|
|
|
}
|
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
static void read_uint(const char **line, unsigned int *u, bool is_uniform)
|
2023-03-17 12:35:13 +01:00
|
|
|
{
|
|
|
|
char *rest;
|
|
|
|
unsigned long val;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
val = strtoul(*line, &rest, 0);
|
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
if (errno != 0 || (is_uniform && *rest != '\0' && !isspace((unsigned char)*rest)))
|
2023-03-17 12:35:13 +01:00
|
|
|
fatal_error("Malformed uint constant '%s'.\n", *line);
|
|
|
|
|
|
|
|
*u = val;
|
|
|
|
if (*u != val)
|
|
|
|
fatal_error("Out of range uint constant '%.*s'.\n", (int)(rest - *line), *line);
|
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
*line = rest + (!is_uniform && *rest == ',');
|
2023-03-17 12:35:13 +01:00
|
|
|
}
|
|
|
|
|
2024-02-01 16:02:58 +10:00
|
|
|
static void read_int4(const char **line, struct ivec4 *v, bool is_uniform)
|
2023-03-17 12:35:13 +01:00
|
|
|
{
|
2024-02-01 16:02:58 +10:00
|
|
|
read_int(line, &v->x, is_uniform);
|
|
|
|
read_int(line, &v->y, is_uniform);
|
|
|
|
read_int(line, &v->z, is_uniform);
|
|
|
|
read_int(line, &v->w, is_uniform);
|
2023-03-17 12:35:13 +01:00
|
|
|
}
|
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
static void read_uint4(const char **line, struct uvec4 *v, bool is_uniform)
|
2023-03-17 12:35:13 +01:00
|
|
|
{
|
2023-10-13 16:27:44 -05:00
|
|
|
read_uint(line, &v->x, is_uniform);
|
|
|
|
read_uint(line, &v->y, is_uniform);
|
|
|
|
read_uint(line, &v->z, is_uniform);
|
|
|
|
read_uint(line, &v->w, is_uniform);
|
2023-03-17 12:35:13 +01:00
|
|
|
}
|
|
|
|
|
2024-02-26 14:31:54 +10:00
|
|
|
static void read_int64(const char **line, int64_t *i, bool is_uniform)
|
2023-11-10 14:48:23 +10:00
|
|
|
{
|
|
|
|
char *rest;
|
|
|
|
int64_t val;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
val = strtoll(*line, &rest, 0);
|
|
|
|
|
2024-02-26 14:31:54 +10:00
|
|
|
if (errno != 0 || (is_uniform && *rest != '\0' && !isspace((unsigned char)*rest)))
|
2023-11-10 14:48:23 +10:00
|
|
|
fatal_error("Malformed int64 constant '%s'.\n", *line);
|
|
|
|
|
|
|
|
*i = val;
|
2024-02-26 14:31:54 +10:00
|
|
|
*line = rest + (!is_uniform && *rest == ',');
|
2023-11-10 14:48:23 +10:00
|
|
|
}
|
|
|
|
|
2024-02-26 14:31:54 +10:00
|
|
|
static void read_uint64(const char **line, uint64_t *u, bool is_uniform)
|
2023-11-10 14:48:23 +10:00
|
|
|
{
|
|
|
|
char *rest;
|
|
|
|
uint64_t val;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
val = strtoull(*line, &rest, 0);
|
|
|
|
|
2024-02-26 14:31:54 +10:00
|
|
|
if (errno != 0 || (is_uniform && *rest != '\0' && !isspace((unsigned char)*rest)))
|
2023-11-10 14:48:23 +10:00
|
|
|
fatal_error("Malformed uint64 constant '%s'.\n", *line);
|
|
|
|
|
|
|
|
*u = val;
|
2024-02-26 14:31:54 +10:00
|
|
|
*line = rest + (!is_uniform && *rest == ',');
|
2023-11-10 14:48:23 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void read_int64_t2(const char **line, struct i64vec2 *v)
|
|
|
|
{
|
2024-02-26 14:31:54 +10:00
|
|
|
read_int64(line, &v->x, true);
|
|
|
|
read_int64(line, &v->y, true);
|
2023-11-10 14:48:23 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void read_uint64_t2(const char **line, struct u64vec2 *v)
|
|
|
|
{
|
2024-02-26 14:31:54 +10:00
|
|
|
read_uint64(line, &v->x, true);
|
|
|
|
read_uint64(line, &v->y, true);
|
2023-11-10 14:48:23 +10:00
|
|
|
}
|
|
|
|
|
2024-10-21 00:21:00 +02:00
|
|
|
static struct resource *parse_resource_reference(struct shader_runner *runner, const char **const line)
|
|
|
|
{
|
|
|
|
enum resource_type type;
|
|
|
|
unsigned int slot = 0;
|
|
|
|
|
|
|
|
if (match_string(*line, "dsv", line))
|
|
|
|
type = RESOURCE_TYPE_DEPTH_STENCIL;
|
|
|
|
else if (match_string(*line, "rtv", line))
|
|
|
|
type = RESOURCE_TYPE_RENDER_TARGET;
|
|
|
|
else if (match_string(*line, "srv", line))
|
|
|
|
type = RESOURCE_TYPE_TEXTURE;
|
|
|
|
else if (match_string(*line, "uav", line))
|
|
|
|
type = RESOURCE_TYPE_UAV;
|
|
|
|
else if (match_string(*line, "vb", line))
|
|
|
|
type = RESOURCE_TYPE_VERTEX_BUFFER;
|
|
|
|
else
|
|
|
|
fatal_error("Malformed resource reference '%s'.\n", *line);
|
|
|
|
|
|
|
|
if (type != RESOURCE_TYPE_DEPTH_STENCIL)
|
|
|
|
read_uint(line, &slot, false);
|
|
|
|
|
|
|
|
return shader_runner_get_resource(runner, type, slot);
|
|
|
|
}
|
|
|
|
|
2022-03-19 12:35:31 -05:00
|
|
|
static void parse_test_directive(struct shader_runner *runner, const char *line)
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2024-01-29 20:07:39 -03:00
|
|
|
bool skip_directive = false;
|
|
|
|
const char *line_ini;
|
|
|
|
bool match = true;
|
2022-06-08 18:18:38 -05:00
|
|
|
char *rest;
|
2021-08-13 16:37:31 -05:00
|
|
|
int ret;
|
2022-06-08 18:18:38 -05:00
|
|
|
|
2022-04-14 12:52:33 +02:00
|
|
|
runner->is_todo = false;
|
2024-11-05 21:56:26 +01:00
|
|
|
runner->is_bug = false;
|
2022-04-14 12:52:33 +02:00
|
|
|
|
2024-01-29 20:07:39 -03:00
|
|
|
while (match)
|
2023-11-10 18:37:40 -03:00
|
|
|
{
|
2024-01-29 20:07:39 -03:00
|
|
|
match = false;
|
|
|
|
|
2024-03-19 12:36:23 +01:00
|
|
|
if (match_string_with_args(runner, line, "todo", &line))
|
2024-01-29 20:07:39 -03:00
|
|
|
{
|
|
|
|
runner->is_todo = true;
|
|
|
|
match = true;
|
|
|
|
}
|
|
|
|
|
2024-11-05 21:56:26 +01:00
|
|
|
if (match_string_with_args(runner, line, "bug", &line))
|
|
|
|
{
|
|
|
|
runner->is_bug = true;
|
|
|
|
match = true;
|
|
|
|
}
|
|
|
|
|
2024-01-29 20:07:39 -03:00
|
|
|
line_ini = line;
|
2024-03-19 12:36:23 +01:00
|
|
|
if (match_string_with_args(runner, line, "if", &line))
|
2024-01-29 20:07:39 -03:00
|
|
|
{
|
|
|
|
match = true;
|
|
|
|
}
|
|
|
|
else if (line != line_ini)
|
|
|
|
{
|
|
|
|
/* Matched "if" but for other shader models. */
|
|
|
|
skip_directive = true;
|
|
|
|
match = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skip_directive)
|
|
|
|
{
|
|
|
|
const char *new_line;
|
|
|
|
|
|
|
|
if ((new_line = strchr(line, '\n')))
|
|
|
|
line = new_line + 1;
|
|
|
|
else
|
|
|
|
line += strlen(line);
|
|
|
|
return;
|
2023-11-10 18:37:40 -03:00
|
|
|
}
|
2022-04-14 12:52:33 +02:00
|
|
|
|
2021-08-13 16:37:31 -05:00
|
|
|
if (match_string(line, "dispatch", &line))
|
|
|
|
{
|
|
|
|
unsigned int x, y, z;
|
|
|
|
|
|
|
|
ret = sscanf(line, "%u %u %u", &x, &y, &z);
|
|
|
|
if (ret < 3)
|
|
|
|
fatal_error("Malformed dispatch arguments '%s'.\n", line);
|
|
|
|
|
|
|
|
runner->last_render_failed = !runner->ops->dispatch(runner, x, y, z);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
ok(!runner->last_render_failed, "Dispatch failed.\n");
|
2021-08-13 16:37:31 -05:00
|
|
|
}
|
2024-04-15 10:37:37 +10:00
|
|
|
else if (match_string(line, "clear rtv", &line))
|
|
|
|
{
|
|
|
|
struct resource *resource;
|
|
|
|
unsigned int slot;
|
|
|
|
struct vec4 v;
|
|
|
|
|
|
|
|
if (sscanf(line, "%u %f %f %f %f", &slot, &v.x, &v.y, &v.z, &v.w) < 5)
|
|
|
|
fatal_error("Malformed rtv clear arguments '%s'.\n", line);
|
|
|
|
|
2024-05-17 19:53:12 -05:00
|
|
|
set_default_target(runner);
|
|
|
|
|
2024-04-15 10:37:37 +10:00
|
|
|
if (!(resource = shader_runner_get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, slot)))
|
|
|
|
fatal_error("Resource not found.\n");
|
|
|
|
runner->ops->clear(runner, resource, &v);
|
|
|
|
}
|
2024-04-15 10:33:15 +10:00
|
|
|
else if (match_string(line, "clear dsv", &line))
|
|
|
|
{
|
|
|
|
struct resource *resource;
|
|
|
|
struct vec4 v = {0};
|
|
|
|
|
|
|
|
if (!sscanf(line, "%f", &v.x))
|
|
|
|
fatal_error("Malformed dsv clear arguments '%s'.\n", line);
|
|
|
|
|
|
|
|
if (!(resource = shader_runner_get_resource(runner, RESOURCE_TYPE_DEPTH_STENCIL, 0)))
|
|
|
|
fatal_error("Resource not found.\n");
|
|
|
|
runner->ops->clear(runner, resource, &v);
|
|
|
|
}
|
2024-08-31 18:54:44 +02:00
|
|
|
else if (match_string(line, "depth-bounds", &line))
|
|
|
|
{
|
|
|
|
if (sscanf(line, "%f %f", &runner->depth_min, &runner->depth_max) != 2)
|
|
|
|
fatal_error("Malformed depth-bounds arguments '%s'.\n", line);
|
2024-10-05 07:46:00 -05:00
|
|
|
if (!runner->caps->shader_caps[SHADER_CAP_DEPTH_BOUNDS])
|
2024-08-31 18:54:44 +02:00
|
|
|
fatal_error("depth-bounds set but runner does not support depth bounds testing.");
|
|
|
|
runner->depth_bounds = true;
|
|
|
|
}
|
2024-04-15 10:33:15 +10:00
|
|
|
else if (match_string(line, "depth", &line))
|
|
|
|
{
|
2024-05-17 19:53:12 -05:00
|
|
|
runner->depth_func = parse_comparison_func(line, &line);
|
2024-04-15 10:33:15 +10:00
|
|
|
}
|
2021-08-13 16:37:31 -05:00
|
|
|
else if (match_string(line, "draw quad", &line))
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2022-04-07 18:58:13 -05:00
|
|
|
struct resource_params params;
|
|
|
|
struct input_element *element;
|
2024-01-24 19:44:47 -03:00
|
|
|
unsigned int i;
|
2022-04-07 18:58:13 -05:00
|
|
|
|
|
|
|
/* For simplicity, draw a large triangle instead. */
|
|
|
|
static const struct vec2 quad[] =
|
|
|
|
{
|
|
|
|
{-2.0f, -2.0f},
|
|
|
|
{-2.0f, 4.0f},
|
|
|
|
{ 4.0f, -2.0f},
|
|
|
|
};
|
|
|
|
|
2022-03-21 20:42:15 -05:00
|
|
|
static const char vs_source[] =
|
2022-08-15 19:53:55 -05:00
|
|
|
"float4 main(float4 pos : position) : sv_position\n"
|
2022-03-21 20:42:15 -05:00
|
|
|
"{\n"
|
2022-08-15 19:53:55 -05:00
|
|
|
" return pos;\n"
|
2022-03-21 20:42:15 -05:00
|
|
|
"}";
|
|
|
|
|
2023-10-27 11:11:57 -05:00
|
|
|
if (!runner->shader_source[SHADER_TYPE_HS] != !runner->shader_source[SHADER_TYPE_DS])
|
2024-04-08 14:37:32 +10:00
|
|
|
fatal_error("Have a domain or hull shader but not both.\n");
|
|
|
|
|
2024-05-17 19:51:56 -05:00
|
|
|
set_default_target(runner);
|
2022-06-08 18:18:37 -05:00
|
|
|
|
2024-01-24 19:44:47 -03:00
|
|
|
for (i = 0; i < runner->input_element_count; ++i)
|
|
|
|
free(runner->input_elements[i].name);
|
|
|
|
|
2022-04-07 18:58:13 -05:00
|
|
|
vkd3d_array_reserve((void **)&runner->input_elements, &runner->input_element_capacity,
|
|
|
|
1, sizeof(*runner->input_elements));
|
|
|
|
element = &runner->input_elements[0];
|
2022-08-15 19:53:55 -05:00
|
|
|
element->name = strdup("position");
|
2022-04-07 18:58:13 -05:00
|
|
|
element->slot = 0;
|
|
|
|
element->format = DXGI_FORMAT_R32G32_FLOAT;
|
|
|
|
element->texel_size = sizeof(*quad);
|
|
|
|
element->index = 0;
|
|
|
|
runner->input_element_count = 1;
|
|
|
|
|
|
|
|
memset(¶ms, 0, sizeof(params));
|
2024-06-17 16:01:04 -05:00
|
|
|
params.desc.slot = 0;
|
|
|
|
params.desc.type = RESOURCE_TYPE_VERTEX_BUFFER;
|
|
|
|
params.desc.dimension = RESOURCE_DIMENSION_BUFFER;
|
|
|
|
params.desc.width = sizeof(quad);
|
2022-04-07 18:58:13 -05:00
|
|
|
params.data = malloc(sizeof(quad));
|
|
|
|
memcpy(params.data, quad, sizeof(quad));
|
|
|
|
params.data_size = sizeof(quad);
|
2024-04-10 13:51:06 +10:00
|
|
|
set_resource(runner, ¶ms);
|
2024-01-24 18:50:30 -03:00
|
|
|
free(params.data);
|
2022-04-07 18:58:13 -05:00
|
|
|
|
2023-10-27 11:11:57 -05:00
|
|
|
if (!runner->shader_source[SHADER_TYPE_VS])
|
|
|
|
runner->shader_source[SHADER_TYPE_VS] = strdup(vs_source);
|
2022-03-21 20:42:15 -05:00
|
|
|
|
2024-06-18 23:53:49 -05:00
|
|
|
runner->sample_count = 1;
|
|
|
|
for (i = 0; i < runner->resource_count; ++i)
|
|
|
|
{
|
|
|
|
if (runner->resources[i]->desc.type == RESOURCE_TYPE_RENDER_TARGET
|
|
|
|
|| runner->resources[i]->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
|
|
|
|
runner->sample_count = max(runner->sample_count, runner->resources[i]->desc.sample_count);
|
|
|
|
}
|
|
|
|
|
2024-04-22 12:55:44 +10:00
|
|
|
runner->last_render_failed = !runner->ops->draw(runner, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, 3, 1);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
ok(!runner->last_render_failed, "Draw failed.\n");
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
2022-03-21 20:42:21 -05:00
|
|
|
else if (match_string(line, "draw", &line))
|
|
|
|
{
|
2024-04-22 12:55:44 +10:00
|
|
|
unsigned int vertex_count, instance_count;
|
2022-03-21 20:42:21 -05:00
|
|
|
D3D_PRIMITIVE_TOPOLOGY topology;
|
|
|
|
|
2023-10-27 11:11:57 -05:00
|
|
|
if (!runner->shader_source[SHADER_TYPE_HS] != !runner->shader_source[SHADER_TYPE_DS])
|
2024-04-08 14:37:32 +10:00
|
|
|
fatal_error("Have a domain or hull shader but not both.\n");
|
|
|
|
|
2024-05-17 19:51:56 -05:00
|
|
|
set_default_target(runner);
|
2022-06-08 18:18:37 -05:00
|
|
|
|
2022-03-21 20:42:21 -05:00
|
|
|
if (match_string(line, "triangle list", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
2022-04-05 12:33:05 +02:00
|
|
|
else if (match_string(line, "triangle strip", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
2024-04-19 12:33:56 +10:00
|
|
|
else if (match_string(line, "point list", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
|
2024-04-08 14:37:32 +10:00
|
|
|
else if (match_string(line, "1 control point patch list", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST;
|
|
|
|
else if (match_string(line, "2 control point patch list", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST;
|
|
|
|
else if (match_string(line, "3 control point patch list", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;
|
|
|
|
else if (match_string(line, "4 control point patch list", &line))
|
|
|
|
topology = D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST;
|
2022-03-21 20:42:21 -05:00
|
|
|
else
|
|
|
|
fatal_error("Unknown primitive topology '%s'.\n", line);
|
|
|
|
|
|
|
|
vertex_count = strtoul(line, &rest, 10);
|
|
|
|
if (line == rest)
|
|
|
|
fatal_error("Malformed vertex count '%s'.\n", line);
|
2024-04-22 12:55:44 +10:00
|
|
|
instance_count = strtoul(line = rest, &rest, 10);
|
|
|
|
if (line == rest)
|
|
|
|
instance_count = 1;
|
2022-03-21 20:42:21 -05:00
|
|
|
|
2024-06-18 23:53:49 -05:00
|
|
|
runner->sample_count = 1;
|
|
|
|
for (unsigned int i = 0; i < runner->resource_count; ++i)
|
|
|
|
{
|
|
|
|
if (runner->resources[i]->desc.type == RESOURCE_TYPE_RENDER_TARGET
|
|
|
|
|| runner->resources[i]->desc.type == RESOURCE_TYPE_DEPTH_STENCIL)
|
|
|
|
runner->sample_count = max(runner->sample_count, runner->resources[i]->desc.sample_count);
|
|
|
|
}
|
|
|
|
|
2024-04-22 12:55:44 +10:00
|
|
|
runner->last_render_failed = !runner->ops->draw(runner, topology, vertex_count, instance_count);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
ok(!runner->last_render_failed, "Draw failed.\n");
|
2022-03-21 20:42:21 -05:00
|
|
|
}
|
2024-10-21 00:21:00 +02:00
|
|
|
else if (match_string(line, "copy", &line))
|
|
|
|
{
|
|
|
|
struct resource *src, *dst;
|
|
|
|
|
|
|
|
if (!(src = parse_resource_reference(runner, &line)))
|
|
|
|
fatal_error("Undefined source resource.\n");
|
|
|
|
if (!(dst = parse_resource_reference(runner, &line)))
|
|
|
|
fatal_error("Undefined destination resource.\n");
|
|
|
|
|
|
|
|
if (src->desc.dimension != dst->desc.dimension
|
|
|
|
|| src->desc.texel_size != dst->desc.texel_size
|
|
|
|
|| src->desc.width != dst->desc.width
|
|
|
|
|| src->desc.height != dst->desc.height
|
|
|
|
|| src->desc.level_count != dst->desc.level_count
|
|
|
|
|| src->desc.sample_count != dst->desc.sample_count)
|
|
|
|
fatal_error("Resource dimensions don't match.\n");
|
|
|
|
|
2024-10-31 13:56:19 +01:00
|
|
|
ret = runner->ops->copy(runner, src, dst);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
ok(ret, "Failed to copy resource.\n");
|
2024-10-21 00:21:00 +02:00
|
|
|
}
|
2022-04-18 08:33:58 +02:00
|
|
|
else if (match_string(line, "probe", &line))
|
2020-09-30 21:01:21 -05:00
|
|
|
{
|
2022-06-08 18:18:39 -05:00
|
|
|
unsigned int left, top, right, bottom, ulps, slot;
|
2022-05-17 15:45:41 +02:00
|
|
|
struct resource_readback *rb;
|
2022-06-08 18:18:37 -05:00
|
|
|
struct resource *resource;
|
2024-02-13 15:08:03 +10:00
|
|
|
bool is_signed = false;
|
2020-09-30 21:01:21 -05:00
|
|
|
RECT rect;
|
2021-08-13 16:37:31 -05:00
|
|
|
int len;
|
2020-09-30 21:01:21 -05:00
|
|
|
|
2022-04-14 12:52:32 +02:00
|
|
|
if (runner->last_render_failed)
|
|
|
|
return;
|
|
|
|
|
2022-06-08 18:18:38 -05:00
|
|
|
if (match_string(line, "uav", &line))
|
|
|
|
{
|
2022-06-08 18:18:39 -05:00
|
|
|
slot = strtoul(line, &rest, 10);
|
2022-06-08 18:18:38 -05:00
|
|
|
|
|
|
|
if (rest == line)
|
|
|
|
fatal_error("Malformed UAV index '%s'.\n", line);
|
|
|
|
line = rest;
|
|
|
|
|
2023-09-22 07:31:31 +02:00
|
|
|
resource = shader_runner_get_resource(runner, RESOURCE_TYPE_UAV, slot);
|
2022-06-08 18:18:38 -05:00
|
|
|
}
|
2024-01-24 16:35:39 -03:00
|
|
|
else if (match_string(line, "rtv", &line))
|
2022-06-08 18:18:39 -05:00
|
|
|
{
|
|
|
|
slot = strtoul(line, &rest, 10);
|
|
|
|
|
|
|
|
if (rest == line)
|
|
|
|
fatal_error("Malformed render target index '%s'.\n", line);
|
|
|
|
line = rest;
|
|
|
|
|
2023-09-22 07:31:31 +02:00
|
|
|
resource = shader_runner_get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, slot);
|
2022-06-08 18:18:39 -05:00
|
|
|
}
|
2024-04-15 10:33:15 +10:00
|
|
|
else if (match_string(line, "dsv", &line))
|
|
|
|
{
|
|
|
|
resource = shader_runner_get_resource(runner, RESOURCE_TYPE_DEPTH_STENCIL, 0);
|
|
|
|
}
|
2022-06-08 18:18:38 -05:00
|
|
|
else
|
|
|
|
{
|
2023-09-22 07:31:31 +02:00
|
|
|
resource = shader_runner_get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0);
|
2022-06-08 18:18:38 -05:00
|
|
|
}
|
|
|
|
|
2022-06-08 18:18:37 -05:00
|
|
|
rb = runner->ops->get_resource_readback(runner, resource);
|
|
|
|
|
2024-02-10 13:16:22 -06:00
|
|
|
if (sscanf(line, " ( %d , %d , %d , %d )%n", &left, &top, &right, &bottom, &len) == 4)
|
2022-04-18 08:33:58 +02:00
|
|
|
{
|
|
|
|
set_rect(&rect, left, top, right, bottom);
|
|
|
|
line += len;
|
|
|
|
}
|
2022-06-08 18:18:38 -05:00
|
|
|
else if (sscanf(line, " ( %u , %u )%n", &left, &top, &len) == 2)
|
2022-04-18 08:33:58 +02:00
|
|
|
{
|
|
|
|
set_rect(&rect, left, top, left + 1, top + 1);
|
|
|
|
line += len;
|
|
|
|
}
|
2024-01-24 16:35:39 -03:00
|
|
|
else if (sscanf(line, " ( %u )%n", &left, &len) == 1)
|
|
|
|
{
|
|
|
|
set_rect(&rect, left, 0, left + 1, 1);
|
|
|
|
line += len;
|
|
|
|
}
|
2022-05-17 15:45:41 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
}
|
2020-10-01 23:09:44 -05:00
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
if (match_string(line, "rgbaui", &line))
|
|
|
|
{
|
|
|
|
struct uvec4 v;
|
|
|
|
|
|
|
|
if (*line != '(')
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
++line;
|
|
|
|
read_uint4(&line, &v, false);
|
|
|
|
line = close_parentheses(line);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_uvec4(rb, &rect, &v);
|
2023-10-13 16:27:44 -05:00
|
|
|
}
|
2024-02-01 16:02:58 +10:00
|
|
|
else if (match_string(line, "rgbai", &line))
|
|
|
|
{
|
|
|
|
struct ivec4 v;
|
|
|
|
|
|
|
|
if (*line != '(')
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
++line;
|
|
|
|
read_int4(&line, &v, false);
|
|
|
|
line = close_parentheses(line);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_ivec4(rb, &rect, &v);
|
2024-02-01 16:02:58 +10:00
|
|
|
}
|
2023-10-13 16:27:44 -05:00
|
|
|
else if (match_string(line, "rgba", &line))
|
2022-05-17 15:45:42 +02:00
|
|
|
{
|
|
|
|
struct vec4 v;
|
2022-04-14 12:52:32 +02:00
|
|
|
|
2022-05-17 15:45:42 +02:00
|
|
|
ret = sscanf(line, "( %f , %f , %f , %f ) %u", &v.x, &v.y, &v.z, &v.w, &ulps);
|
|
|
|
if (ret < 4)
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
if (ret < 5)
|
|
|
|
ulps = 0;
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_vec4(rb, &rect, &v, ulps);
|
2022-05-17 15:45:42 +02:00
|
|
|
}
|
2024-10-22 12:53:19 +02:00
|
|
|
else if (match_string(line, "rg", &line))
|
|
|
|
{
|
|
|
|
struct vec4 v;
|
|
|
|
|
|
|
|
ret = sscanf(line, "( %f , %f ) %u", &v.x, &v.y, &ulps);
|
|
|
|
if (ret < 2)
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
if (ret < 3)
|
|
|
|
ulps = 0;
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_vec2(rb, &rect, &v, ulps);
|
2024-10-22 12:53:19 +02:00
|
|
|
}
|
2024-02-13 15:08:03 +10:00
|
|
|
else if (match_string(line, "rui", &line) || (is_signed = match_string(line, "ri", &line)))
|
2023-10-13 16:27:44 -05:00
|
|
|
{
|
|
|
|
unsigned int expect;
|
|
|
|
D3D12_BOX box;
|
|
|
|
|
|
|
|
box.left = rect.left;
|
|
|
|
box.right = rect.right;
|
|
|
|
box.top = rect.top;
|
|
|
|
box.bottom = rect.bottom;
|
|
|
|
box.front = 0;
|
|
|
|
box.back = 1;
|
|
|
|
if (*line != '(')
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
++line;
|
2024-02-13 15:08:03 +10:00
|
|
|
if (is_signed)
|
|
|
|
read_int(&line, (int *)&expect, false);
|
|
|
|
else
|
|
|
|
read_uint(&line, &expect, false);
|
2023-10-13 16:27:44 -05:00
|
|
|
line = close_parentheses(line);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_uint(rb, &box, expect, 0);
|
2023-10-13 16:27:44 -05:00
|
|
|
}
|
2024-12-03 12:11:16 +10:00
|
|
|
else if (match_string(line, "rgui64", &line))
|
|
|
|
{
|
|
|
|
struct u64vec2 v;
|
|
|
|
|
|
|
|
if (*line != '(')
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
++line;
|
|
|
|
read_uint64(&line, &v.x, false);
|
|
|
|
read_uint64(&line, &v.y, false);
|
|
|
|
line = close_parentheses(line);
|
|
|
|
todo_if(runner->is_todo) check_readback_data_u64vec2(rb, &rect, &v);
|
|
|
|
}
|
2024-02-26 14:31:54 +10:00
|
|
|
else if (match_string(line, "rui64", &line) || (is_signed = match_string(line, "ri64", &line)))
|
|
|
|
{
|
|
|
|
uint64_t expect;
|
|
|
|
D3D12_BOX box;
|
|
|
|
|
|
|
|
box.left = rect.left;
|
|
|
|
box.right = rect.right;
|
|
|
|
box.top = rect.top;
|
|
|
|
box.bottom = rect.bottom;
|
|
|
|
box.front = 0;
|
|
|
|
box.back = 1;
|
|
|
|
if (*line != '(')
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
++line;
|
|
|
|
if (is_signed)
|
|
|
|
read_int64(&line, (int64_t *)&expect, false);
|
|
|
|
else
|
|
|
|
read_uint64(&line, &expect, false);
|
|
|
|
line = close_parentheses(line);
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_uint64(rb, &box, expect, 0);
|
2024-02-26 14:31:54 +10:00
|
|
|
}
|
2024-12-03 11:56:01 +10:00
|
|
|
else if (match_string(line, "rgd", &line))
|
|
|
|
{
|
|
|
|
struct dvec2 v;
|
|
|
|
|
|
|
|
ret = sscanf(line, "( %lf , %lf ) %u", &v.x, &v.y, &ulps);
|
|
|
|
if (ret < 2)
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
if (ret < 3)
|
|
|
|
ulps = 0;
|
|
|
|
todo_if(runner->is_todo) check_readback_data_dvec2(rb, &rect, &v, ulps);
|
|
|
|
}
|
2024-02-26 14:31:54 +10:00
|
|
|
else if (match_string(line, "rd", &line))
|
|
|
|
{
|
|
|
|
double expect;
|
|
|
|
|
|
|
|
ret = sscanf(line, "( %lf ) %u", &expect, &ulps);
|
|
|
|
if (ret < 1)
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
if (ret < 2)
|
|
|
|
ulps = 0;
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_double(rb, &rect, expect, ulps);
|
2024-02-26 14:31:54 +10:00
|
|
|
}
|
2022-05-17 15:45:42 +02:00
|
|
|
else if (match_string(line, "r", &line))
|
|
|
|
{
|
|
|
|
float expect;
|
|
|
|
|
|
|
|
ret = sscanf(line, "( %f ) %u", &expect, &ulps);
|
|
|
|
if (ret < 1)
|
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
|
|
|
if (ret < 2)
|
|
|
|
ulps = 0;
|
2024-11-05 21:56:26 +01:00
|
|
|
todo_if(runner->is_todo) bug_if(runner->is_bug)
|
|
|
|
check_readback_data_float(rb, &rect, expect, ulps);
|
2022-05-17 15:45:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-05 19:35:50 +01:00
|
|
|
fatal_error("Malformed probe arguments '%s'.\n", line);
|
2022-05-17 15:45:42 +02:00
|
|
|
}
|
2020-10-01 23:09:44 -05:00
|
|
|
|
2022-05-17 15:45:41 +02:00
|
|
|
runner->ops->release_readback(runner, rb);
|
2020-09-30 21:01:21 -05:00
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
else if (match_string(line, "uniform", &line))
|
|
|
|
{
|
|
|
|
unsigned int offset;
|
|
|
|
|
|
|
|
if (!sscanf(line, "%u", &offset))
|
2022-09-27 13:35:16 -05:00
|
|
|
fatal_error("Malformed uniform offset '%s'.\n", line);
|
2020-09-30 21:01:18 -05:00
|
|
|
line = strchr(line, ' ') + 1;
|
|
|
|
|
|
|
|
if (match_string(line, "float4", &line))
|
|
|
|
{
|
|
|
|
struct vec4 v;
|
|
|
|
|
|
|
|
if (sscanf(line, "%f %f %f %f", &v.x, &v.y, &v.z, &v.w) < 4)
|
2021-11-05 19:35:50 +01:00
|
|
|
fatal_error("Malformed float4 constant '%s'.\n", line);
|
2022-03-19 12:35:31 -05:00
|
|
|
set_uniforms(runner, offset, 4, &v);
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
2021-09-09 21:11:32 -05:00
|
|
|
else if (match_string(line, "float", &line))
|
|
|
|
{
|
|
|
|
float f;
|
|
|
|
|
|
|
|
if (sscanf(line, "%f", &f) < 1)
|
2021-11-05 19:35:50 +01:00
|
|
|
fatal_error("Malformed float constant '%s'.\n", line);
|
2022-03-19 12:35:31 -05:00
|
|
|
set_uniforms(runner, offset, 1, &f);
|
2021-09-09 21:11:32 -05:00
|
|
|
}
|
2023-11-10 14:48:23 +10:00
|
|
|
else if (match_string(line, "double2", &line))
|
|
|
|
{
|
|
|
|
struct dvec2 v;
|
|
|
|
|
|
|
|
if (sscanf(line, "%lf %lf", &v.x, &v.y) < 2)
|
|
|
|
fatal_error("Malformed double2 constant '%s'.\n", line);
|
|
|
|
set_uniforms(runner, offset, 4, &v);
|
|
|
|
}
|
2023-03-17 12:35:13 +01:00
|
|
|
else if (match_string(line, "int4", &line))
|
|
|
|
{
|
|
|
|
struct ivec4 v;
|
|
|
|
|
2024-02-01 16:02:58 +10:00
|
|
|
read_int4(&line, &v, true);
|
2023-03-17 12:35:13 +01:00
|
|
|
set_uniforms(runner, offset, 4, &v);
|
|
|
|
}
|
|
|
|
else if (match_string(line, "uint4", &line))
|
2022-02-02 13:46:13 +01:00
|
|
|
{
|
2023-03-17 12:35:13 +01:00
|
|
|
struct uvec4 v;
|
2022-02-02 13:46:13 +01:00
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
read_uint4(&line, &v, true);
|
2023-03-17 12:35:13 +01:00
|
|
|
set_uniforms(runner, offset, 4, &v);
|
2022-02-02 13:46:13 +01:00
|
|
|
}
|
2021-09-09 21:11:32 -05:00
|
|
|
else if (match_string(line, "int", &line))
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2024-02-13 15:08:03 +10:00
|
|
|
read_int(&line, &i, true);
|
2022-03-19 12:35:31 -05:00
|
|
|
set_uniforms(runner, offset, 1, &i);
|
2021-09-09 21:11:32 -05:00
|
|
|
}
|
2020-09-30 21:01:22 -05:00
|
|
|
else if (match_string(line, "uint", &line))
|
|
|
|
{
|
|
|
|
unsigned int u;
|
|
|
|
|
2023-10-13 16:27:44 -05:00
|
|
|
read_uint(&line, &u, true);
|
2022-03-19 12:35:31 -05:00
|
|
|
set_uniforms(runner, offset, 1, &u);
|
2020-09-30 21:01:22 -05:00
|
|
|
}
|
2023-11-10 14:48:23 +10:00
|
|
|
else if (match_string(line, "int64_t2", &line))
|
|
|
|
{
|
|
|
|
struct i64vec2 v;
|
|
|
|
|
|
|
|
read_int64_t2(&line, &v);
|
|
|
|
set_uniforms(runner, offset, 4, &v);
|
|
|
|
}
|
|
|
|
else if (match_string(line, "uint64_t2", &line))
|
|
|
|
{
|
|
|
|
struct u64vec2 v;
|
|
|
|
|
|
|
|
read_uint64_t2(&line, &v);
|
|
|
|
set_uniforms(runner, offset, 4, &v);
|
|
|
|
}
|
2022-09-27 13:35:16 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fatal_error("Unknown uniform type '%s'.\n", line);
|
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
2024-04-04 15:00:26 +10:00
|
|
|
else if (match_string(line, "sample mask", &line))
|
|
|
|
{
|
|
|
|
unsigned int sample_mask;
|
|
|
|
|
|
|
|
read_uint(&line, &sample_mask, false);
|
|
|
|
runner->sample_mask = sample_mask;
|
|
|
|
}
|
2024-05-17 19:53:12 -05:00
|
|
|
else if (match_string(line, "alpha test", &line))
|
|
|
|
{
|
|
|
|
runner->alpha_test_func = (enum vkd3d_shader_comparison_func)parse_comparison_func(line, &line);
|
|
|
|
runner->alpha_test_ref = strtof(line, &rest);
|
|
|
|
line = rest;
|
|
|
|
}
|
2024-07-11 17:31:02 -05:00
|
|
|
else if (match_string(line, "shade mode", &line))
|
|
|
|
{
|
|
|
|
if (match_string(line, "flat", &line))
|
|
|
|
runner->flat_shading = true;
|
|
|
|
else
|
|
|
|
runner->flat_shading = false;
|
|
|
|
}
|
2024-07-16 19:49:30 -05:00
|
|
|
else if (match_string(line, "clip-plane", &line))
|
|
|
|
{
|
|
|
|
unsigned int index;
|
|
|
|
struct vec4 *v;
|
|
|
|
|
|
|
|
index = strtoul(line, (char **)&rest, 10);
|
|
|
|
if (rest == line || index >= 8)
|
|
|
|
fatal_error("Malformed clip plane directive '%s'.\n", line);
|
|
|
|
line = rest;
|
|
|
|
|
|
|
|
v = &runner->clip_planes[index];
|
|
|
|
|
|
|
|
if (match_string(line, "disable", &line))
|
|
|
|
runner->clip_plane_mask &= ~(1u << index);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (sscanf(line, "%f %f %f %f", &v->x, &v->y, &v->z, &v->w) < 4)
|
|
|
|
fatal_error("Malformed float4 constant '%s'.\n", line);
|
|
|
|
runner->clip_plane_mask |= (1u << index);
|
|
|
|
}
|
|
|
|
}
|
2024-10-03 16:23:04 -05:00
|
|
|
else if (match_string(line, "point-size", &line))
|
|
|
|
{
|
|
|
|
runner->point_size = strtof(line, &rest);
|
2024-10-03 17:55:33 -05:00
|
|
|
line = rest;
|
|
|
|
runner->point_size_min = strtof(line, &rest);
|
|
|
|
line = rest;
|
|
|
|
runner->point_size_max = strtof(line, &rest);
|
2024-10-03 16:23:04 -05:00
|
|
|
}
|
2024-10-15 19:04:25 -05:00
|
|
|
else if (match_string(line, "point-sprite", &line))
|
|
|
|
{
|
|
|
|
if (match_string(line, "on", &line))
|
|
|
|
runner->point_sprite = true;
|
|
|
|
else
|
|
|
|
runner->point_sprite = false;
|
|
|
|
}
|
2024-10-05 10:26:20 -05:00
|
|
|
else if (match_string(line, "fog", &line))
|
|
|
|
{
|
|
|
|
if (match_string(line, "disable", &line))
|
|
|
|
runner->fog_mode = FOG_MODE_DISABLE;
|
|
|
|
else if (match_string(line, "none", &line))
|
|
|
|
runner->fog_mode = FOG_MODE_NONE;
|
|
|
|
else if (match_string(line, "linear", &line))
|
|
|
|
runner->fog_mode = FOG_MODE_LINEAR;
|
|
|
|
else if (match_string(line, "exp", &line))
|
|
|
|
runner->fog_mode = FOG_MODE_EXP;
|
|
|
|
else if (match_string(line, "exp2", &line))
|
|
|
|
runner->fog_mode = FOG_MODE_EXP2;
|
|
|
|
else
|
|
|
|
fatal_error("Invalid fog mode '%s'.\n", line);
|
2024-11-13 19:16:39 -06:00
|
|
|
|
|
|
|
if (match_string(line, "ortho", &line))
|
|
|
|
runner->ortho_fog = true;
|
|
|
|
if (match_string(line, "non-ortho", &line))
|
|
|
|
runner->ortho_fog = false;
|
|
|
|
|
|
|
|
if (runner->fog_mode == FOG_MODE_LINEAR)
|
|
|
|
{
|
|
|
|
if (sscanf(line, "%f %f", &runner->fog_start, &runner->fog_end) < 2)
|
|
|
|
fatal_error("Malformed fog constants '%s'.\n", line);
|
|
|
|
}
|
2024-11-13 19:39:35 -06:00
|
|
|
else if (runner->fog_mode == FOG_MODE_EXP || runner->fog_mode == FOG_MODE_EXP2)
|
|
|
|
{
|
|
|
|
if (sscanf(line, "%f", &runner->fog_density) < 1)
|
|
|
|
fatal_error("Malformed fog constants '%s'.\n", line);
|
|
|
|
}
|
2024-10-05 10:26:20 -05:00
|
|
|
}
|
|
|
|
else if (match_string(line, "fog-colour", &line))
|
|
|
|
{
|
|
|
|
struct vec4 *v = &runner->fog_colour;
|
|
|
|
|
|
|
|
if (sscanf(line, "%f %f %f %f", &v->x, &v->y, &v->z, &v->w) < 4)
|
|
|
|
fatal_error("Malformed float4 constant '%s'.\n", line);
|
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
else
|
|
|
|
{
|
2021-11-05 19:35:50 +01:00
|
|
|
fatal_error("Unknown test directive '%s'.\n", line);
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-22 07:31:31 +02:00
|
|
|
struct sampler *shader_runner_get_sampler(struct shader_runner *runner, unsigned int slot)
|
2021-11-05 19:35:49 +01:00
|
|
|
{
|
|
|
|
struct sampler *sampler;
|
|
|
|
size_t i;
|
|
|
|
|
2022-03-19 12:35:31 -05:00
|
|
|
for (i = 0; i < runner->sampler_count; ++i)
|
2021-11-05 19:35:49 +01:00
|
|
|
{
|
2022-03-19 12:35:31 -05:00
|
|
|
sampler = &runner->samplers[i];
|
2021-11-05 19:35:49 +01:00
|
|
|
|
|
|
|
if (sampler->slot == slot)
|
|
|
|
return sampler;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-03-21 20:42:18 -05:00
|
|
|
unsigned int get_vb_stride(const struct shader_runner *runner, unsigned int slot)
|
|
|
|
{
|
|
|
|
unsigned int stride = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* We currently don't deal with vertex formats less than 32 bits, so don't
|
|
|
|
* bother with alignment. */
|
|
|
|
for (i = 0; i < runner->input_element_count; ++i)
|
|
|
|
{
|
|
|
|
const struct input_element *element = &runner->input_elements[i];
|
|
|
|
|
|
|
|
if (element->slot == slot)
|
|
|
|
stride += element->texel_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return stride;
|
|
|
|
}
|
|
|
|
|
2023-11-15 17:41:33 -03:00
|
|
|
static HRESULT map_special_hrs(HRESULT hr)
|
2023-04-20 11:09:05 -04:00
|
|
|
{
|
2023-11-15 17:41:33 -03:00
|
|
|
if (hr == 0x88760b59)
|
|
|
|
{
|
|
|
|
trace("Mapping hr %#x (D3DXERR_INVALIDDATA) as %#x.\n", hr, E_FAIL);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
2023-04-20 11:09:05 -04:00
|
|
|
if (hr == 0x80010064)
|
|
|
|
{
|
2023-11-12 02:48:30 +01:00
|
|
|
trace("Mapping unidentified hr %#x as %#x.\n", hr, E_FAIL);
|
2023-04-20 11:09:05 -04:00
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2023-09-21 14:32:25 +10:00
|
|
|
const char *shader_type_string(enum shader_type type)
|
|
|
|
{
|
|
|
|
static const char *const shader_types[] =
|
|
|
|
{
|
|
|
|
[SHADER_TYPE_CS] = "cs",
|
|
|
|
[SHADER_TYPE_PS] = "ps",
|
|
|
|
[SHADER_TYPE_VS] = "vs",
|
2024-04-08 14:37:32 +10:00
|
|
|
[SHADER_TYPE_HS] = "hs",
|
|
|
|
[SHADER_TYPE_DS] = "ds",
|
2024-04-19 12:33:56 +10:00
|
|
|
[SHADER_TYPE_GS] = "gs",
|
2023-10-12 12:51:19 +02:00
|
|
|
[SHADER_TYPE_FX] = "fx",
|
2023-09-21 14:32:25 +10:00
|
|
|
};
|
|
|
|
assert(type < ARRAY_SIZE(shader_types));
|
|
|
|
return shader_types[type];
|
|
|
|
}
|
|
|
|
|
2024-07-04 12:14:52 +10:00
|
|
|
static HRESULT d3d10_blob_from_vkd3d_shader_code(const struct vkd3d_shader_code *blob, ID3D10Blob **blob_out)
|
2023-09-14 19:29:24 +10:00
|
|
|
{
|
|
|
|
ID3D10Blob *d3d_blob;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2024-07-04 12:14:52 +10:00
|
|
|
if (FAILED(hr = D3DCreateBlob(blob->size, (ID3DBlob **)&d3d_blob)))
|
2023-09-14 19:29:24 +10:00
|
|
|
{
|
|
|
|
trace("Failed to create blob, hr %#x.\n", hr);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2024-07-04 12:14:52 +10:00
|
|
|
memcpy(ID3D10Blob_GetBufferPointer(d3d_blob), blob->code, blob->size);
|
2023-09-14 19:29:24 +10:00
|
|
|
*blob_out = d3d_blob;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2024-10-24 15:58:32 -05:00
|
|
|
static HRESULT dxc_compiler_compile_shader(void *dxc_compiler, enum shader_type type,
|
2024-07-04 12:14:52 +10:00
|
|
|
unsigned int compile_options, const char *hlsl, ID3D10Blob **blob_out)
|
2023-09-14 19:29:24 +10:00
|
|
|
{
|
2024-07-04 12:14:52 +10:00
|
|
|
struct vkd3d_shader_code blob;
|
|
|
|
HRESULT hr;
|
2023-09-14 19:29:24 +10:00
|
|
|
|
|
|
|
static const WCHAR *const shader_profiles[] =
|
|
|
|
{
|
|
|
|
[SHADER_TYPE_CS] = L"cs_6_0",
|
|
|
|
[SHADER_TYPE_PS] = L"ps_6_0",
|
|
|
|
[SHADER_TYPE_VS] = L"vs_6_0",
|
2024-04-08 14:37:32 +10:00
|
|
|
[SHADER_TYPE_HS] = L"hs_6_0",
|
|
|
|
[SHADER_TYPE_DS] = L"ds_6_0",
|
2024-04-19 12:33:56 +10:00
|
|
|
[SHADER_TYPE_GS] = L"gs_6_0",
|
2023-09-14 19:29:24 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
*blob_out = NULL;
|
|
|
|
|
2024-07-04 12:14:52 +10:00
|
|
|
if (FAILED(hr = dxc_compile(dxc_compiler, shader_profiles[type], compile_options, hlsl, &blob)))
|
2023-09-14 19:29:24 +10:00
|
|
|
return hr;
|
|
|
|
|
2024-07-04 12:14:52 +10:00
|
|
|
hr = d3d10_blob_from_vkd3d_shader_code(&blob, blob_out);
|
|
|
|
free((void *)blob.code);
|
2023-09-14 19:29:24 +10:00
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2024-10-24 15:58:32 -05:00
|
|
|
ID3D10Blob *compile_hlsl(const struct shader_runner *runner, enum shader_type type)
|
|
|
|
{
|
|
|
|
const char *source = runner->shader_source[type];
|
2024-12-18 23:31:01 +01:00
|
|
|
unsigned int options = runner->compile_options;
|
2024-10-24 15:58:32 -05:00
|
|
|
ID3D10Blob *blob = NULL, *errors = NULL;
|
|
|
|
char profile[7];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
static const char *const shader_models[] =
|
|
|
|
{
|
|
|
|
[SHADER_MODEL_2_0] = "2_0",
|
|
|
|
[SHADER_MODEL_3_0] = "3_0",
|
|
|
|
[SHADER_MODEL_4_0] = "4_0",
|
|
|
|
[SHADER_MODEL_4_1] = "4_1",
|
|
|
|
[SHADER_MODEL_5_0] = "5_0",
|
|
|
|
[SHADER_MODEL_5_1] = "5_1",
|
|
|
|
[SHADER_MODEL_6_0] = "6_0",
|
|
|
|
};
|
|
|
|
|
2024-12-18 23:31:01 +01:00
|
|
|
/* Behaviour is inconsistent between different versions of
|
|
|
|
* d3dcompiler_47.dll. Version 10.0.17134.12 seems to reject
|
|
|
|
* D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY for 5.1 profiles, while
|
|
|
|
* version 10.0.10150.0 apparently doesn't. */
|
|
|
|
if (runner->minimum_shader_model >= SHADER_MODEL_5_1)
|
|
|
|
options &= ~D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
|
|
|
|
|
2024-10-24 15:58:32 -05:00
|
|
|
if (runner->minimum_shader_model >= SHADER_MODEL_6_0)
|
|
|
|
{
|
|
|
|
assert(runner->dxc_compiler);
|
2024-12-18 23:31:01 +01:00
|
|
|
hr = dxc_compiler_compile_shader(runner->dxc_compiler, type, options, source, &blob);
|
2024-10-24 15:58:32 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(profile, "%s_%s", shader_type_string(type), shader_models[runner->minimum_shader_model]);
|
2024-12-18 23:31:01 +01:00
|
|
|
hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", profile, options, 0, &blob, &errors);
|
2024-10-24 15:58:32 -05:00
|
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
|
|
{
|
|
|
|
todo_if (runner->is_todo)
|
|
|
|
ok(false, "Failed to compile shader, hr %#x.\n", hr);
|
|
|
|
}
|
|
|
|
if (errors)
|
|
|
|
{
|
|
|
|
if (vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
|
|
|
|
ID3D10Blob_Release(errors);
|
|
|
|
}
|
|
|
|
return blob;
|
|
|
|
}
|
|
|
|
|
2024-12-10 19:17:56 -06:00
|
|
|
static void compile_shader(struct shader_runner *runner, const char *source,
|
|
|
|
size_t len, enum shader_type type, enum shader_model model)
|
2022-10-30 17:21:12 -05:00
|
|
|
{
|
2024-12-10 19:17:56 -06:00
|
|
|
bool use_dxcompiler = (model >= SHADER_MODEL_6_0);
|
2024-12-18 23:31:01 +01:00
|
|
|
unsigned int options = runner->compile_options;
|
2022-10-30 17:21:12 -05:00
|
|
|
ID3D10Blob *blob = NULL, *errors = NULL;
|
|
|
|
char profile[7];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
static const char *const shader_models[] =
|
|
|
|
{
|
2023-11-15 17:41:33 -03:00
|
|
|
[SHADER_MODEL_2_0] = "2_0",
|
|
|
|
[SHADER_MODEL_3_0] = "3_0",
|
2022-10-30 17:21:12 -05:00
|
|
|
[SHADER_MODEL_4_0] = "4_0",
|
|
|
|
[SHADER_MODEL_4_1] = "4_1",
|
|
|
|
[SHADER_MODEL_5_0] = "5_0",
|
|
|
|
[SHADER_MODEL_5_1] = "5_1",
|
2023-09-14 19:29:24 +10:00
|
|
|
[SHADER_MODEL_6_0] = "6_0",
|
2022-10-30 17:21:12 -05:00
|
|
|
};
|
|
|
|
|
2023-10-12 12:51:19 +02:00
|
|
|
static const char *const effect_models[] =
|
|
|
|
{
|
|
|
|
[SHADER_MODEL_2_0] = "2_0",
|
|
|
|
[SHADER_MODEL_4_0] = "4_0",
|
|
|
|
[SHADER_MODEL_4_1] = "4_1",
|
|
|
|
[SHADER_MODEL_5_0] = "5_0",
|
|
|
|
};
|
|
|
|
|
2024-12-11 23:15:59 -06:00
|
|
|
/* We can let this go through D3DCompile() with the invalid shader model
|
|
|
|
* string, but it returns a unique error code. Just skip it. */
|
|
|
|
if (model < SHADER_MODEL_4_0 && type != SHADER_TYPE_VS && type != SHADER_TYPE_PS && type != SHADER_TYPE_FX)
|
|
|
|
return;
|
|
|
|
if (model < SHADER_MODEL_5_0 && (type == SHADER_TYPE_HS || type == SHADER_TYPE_DS))
|
|
|
|
return;
|
|
|
|
|
2024-12-18 23:31:01 +01:00
|
|
|
/* Behaviour is inconsistent between different versions of
|
|
|
|
* d3dcompiler_47.dll. Version 10.0.17134.12 seems to reject
|
|
|
|
* D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY for 5.1 profiles, while
|
|
|
|
* version 10.0.10150.0 apparently doesn't. */
|
|
|
|
if (model >= SHADER_MODEL_5_1)
|
|
|
|
options &= ~D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
|
|
|
|
|
2023-09-14 19:29:24 +10:00
|
|
|
if (use_dxcompiler)
|
|
|
|
{
|
2024-10-24 15:57:43 -05:00
|
|
|
assert(runner->dxc_compiler);
|
2024-12-18 23:31:01 +01:00
|
|
|
hr = dxc_compiler_compile_shader(runner->dxc_compiler, type, options, source, &blob);
|
2023-09-14 19:29:24 +10:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-10-12 12:51:19 +02:00
|
|
|
if (type == SHADER_TYPE_FX)
|
2024-12-10 19:17:56 -06:00
|
|
|
sprintf(profile, "%s_%s", shader_type_string(type), effect_models[model]);
|
2023-10-12 12:51:19 +02:00
|
|
|
else
|
2024-12-10 19:17:56 -06:00
|
|
|
sprintf(profile, "%s_%s", shader_type_string(type), shader_models[model]);
|
2024-12-18 23:31:01 +01:00
|
|
|
hr = D3DCompile(source, len, NULL, NULL, NULL, "main", profile, options, 0, &blob, &errors);
|
2023-09-14 19:29:24 +10:00
|
|
|
}
|
2023-11-15 17:41:33 -03:00
|
|
|
hr = map_special_hrs(hr);
|
2024-12-10 19:17:56 -06:00
|
|
|
todo_if (runner->hlsl_todo[model])
|
|
|
|
ok(hr == runner->hlsl_hrs[model], "Got unexpected hr %#x.\n", hr);
|
2022-10-30 17:21:12 -05:00
|
|
|
if (hr == S_OK)
|
|
|
|
{
|
|
|
|
ID3D10Blob_Release(blob);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert_that(!blob, "Expected no compiled shader blob.\n");
|
2024-07-04 12:14:52 +10:00
|
|
|
if (!use_dxcompiler)
|
|
|
|
assert_that(!!errors, "Expected non-NULL error blob.\n");
|
2022-10-30 17:21:12 -05:00
|
|
|
}
|
|
|
|
if (errors)
|
|
|
|
{
|
|
|
|
if (vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
|
|
|
|
ID3D10Blob_Release(errors);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
static void read_shader_directive(struct shader_runner *runner, const char *line, const char *src)
|
2023-11-10 18:37:40 -03:00
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
for (unsigned int i = SHADER_MODEL_MIN; i <= SHADER_MODEL_MAX; ++i)
|
|
|
|
{
|
|
|
|
runner->hlsl_hrs[i] = S_OK;
|
|
|
|
runner->hlsl_todo[i] = false;
|
|
|
|
}
|
2023-11-10 18:37:40 -03:00
|
|
|
|
2023-09-14 19:18:58 +10:00
|
|
|
while (*src && *src != ']')
|
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
uint32_t model_mask;
|
2023-11-10 18:37:40 -03:00
|
|
|
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
if (match_string(src, "todo", &src))
|
2023-09-14 19:18:58 +10:00
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
check_qualifier_args(runner, src, &src, &model_mask);
|
|
|
|
for (unsigned int i = SHADER_MODEL_MIN; i <= SHADER_MODEL_MAX; ++i)
|
|
|
|
{
|
|
|
|
/* 'todo' is not meaningful when dxcompiler is in use. */
|
|
|
|
if (i < SHADER_MODEL_6_0 && (model_mask & (1u << i)))
|
|
|
|
runner->hlsl_todo[i] = true;
|
|
|
|
}
|
2023-09-14 19:18:58 +10:00
|
|
|
}
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
else if (match_string(src, "fail", &src))
|
2023-09-14 19:18:58 +10:00
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
check_qualifier_args(runner, src, &src, &model_mask);
|
|
|
|
for (unsigned int i = SHADER_MODEL_MIN; i <= SHADER_MODEL_MAX; ++i)
|
|
|
|
{
|
|
|
|
if (model_mask & (1u << i))
|
|
|
|
runner->hlsl_hrs[i] = E_FAIL;
|
|
|
|
}
|
2023-09-14 19:18:58 +10:00
|
|
|
}
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
else if (match_string(src, "notimpl", &src))
|
2023-09-14 19:29:24 +10:00
|
|
|
{
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
check_qualifier_args(runner, src, &src, &model_mask);
|
|
|
|
for (unsigned int i = SHADER_MODEL_MIN; i <= SHADER_MODEL_MAX; ++i)
|
|
|
|
{
|
|
|
|
if (model_mask & (1u << i))
|
|
|
|
runner->hlsl_hrs[i] = E_NOTIMPL;
|
|
|
|
}
|
2023-09-14 19:18:58 +10:00
|
|
|
}
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
else
|
2023-09-14 19:18:58 +10:00
|
|
|
{
|
|
|
|
fatal_error("Malformed line '%s'.\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(src, "]\n"))
|
|
|
|
fatal_error("Malformed line '%s'.\n", line);
|
|
|
|
}
|
|
|
|
|
2024-08-05 12:58:23 -04:00
|
|
|
static bool check_capabilities(const struct shader_runner *runner, const struct shader_runner_caps *caps)
|
2024-02-19 16:47:11 +01:00
|
|
|
{
|
2024-08-01 19:13:31 -04:00
|
|
|
unsigned int i;
|
|
|
|
|
2024-10-05 07:46:00 -05:00
|
|
|
for (i = 0; i < SHADER_CAP_COUNT; ++i)
|
|
|
|
{
|
|
|
|
if (runner->require_shader_caps[i] && !caps->shader_caps[i])
|
|
|
|
return false;
|
|
|
|
}
|
2024-02-19 16:47:11 +01:00
|
|
|
|
2024-08-01 19:13:31 -04:00
|
|
|
for (i = 0; i < ARRAY_SIZE(runner->require_format_caps); ++i)
|
|
|
|
{
|
|
|
|
if (runner->require_format_caps[i] & ~caps->format_caps[i])
|
|
|
|
return false;
|
|
|
|
}
|
2024-02-19 16:47:11 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-03-19 12:36:23 +01:00
|
|
|
static void trace_tags(const struct shader_runner_caps *caps)
|
|
|
|
{
|
|
|
|
char tags[80], *p;
|
|
|
|
size_t rem;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
p = tags;
|
|
|
|
rem = ARRAY_SIZE(tags);
|
2024-10-05 07:46:00 -05:00
|
|
|
rc = snprintf(p, rem, "%8s:", "tags");
|
2024-03-19 12:36:23 +01:00
|
|
|
p += rc;
|
|
|
|
rem -= rc;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < caps->tag_count; ++i)
|
|
|
|
{
|
|
|
|
rc = snprintf(p, rem, " \"%s\"%s", caps->tags[i], i == caps->tag_count - 1 ? "" : ",");
|
|
|
|
if (!(rc >= 0 && (size_t)rc < rem))
|
|
|
|
{
|
|
|
|
*p = 0;
|
|
|
|
trace("%s\n", tags);
|
|
|
|
|
|
|
|
p = tags;
|
|
|
|
rem = ARRAY_SIZE(tags);
|
2024-10-05 07:46:00 -05:00
|
|
|
rc = snprintf(p, rem, "%8s ", "");
|
2024-03-19 12:36:23 +01:00
|
|
|
--i;
|
|
|
|
}
|
|
|
|
p += rc;
|
|
|
|
rem -= rc;
|
|
|
|
}
|
|
|
|
trace("%s.\n", tags);
|
|
|
|
}
|
|
|
|
|
2024-10-05 07:46:00 -05:00
|
|
|
static void trace_shader_caps(const bool *caps)
|
|
|
|
{
|
2024-10-31 13:53:21 +01:00
|
|
|
bool show_none = true;
|
2024-10-05 07:46:00 -05:00
|
|
|
char buffer[80], *p;
|
|
|
|
size_t rem;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
rem = ARRAY_SIZE(buffer);
|
|
|
|
rc = snprintf(p, rem, "%8s:", "caps");
|
|
|
|
p += rc;
|
|
|
|
rem -= rc;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < SHADER_CAP_COUNT; ++i)
|
|
|
|
{
|
|
|
|
if (!caps[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
rc = snprintf(p, rem, " %s", shader_cap_strings[i]);
|
|
|
|
if (!(rc >= 0 && (size_t)rc < rem))
|
|
|
|
{
|
|
|
|
*p = 0;
|
|
|
|
trace("%s\n", buffer);
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
rem = ARRAY_SIZE(buffer);
|
|
|
|
rc = snprintf(p, rem, "%8s ", "");
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
p += rc;
|
|
|
|
rem -= rc;
|
2024-10-31 13:53:21 +01:00
|
|
|
show_none = false;
|
2024-10-05 07:46:00 -05:00
|
|
|
}
|
2024-10-31 13:53:21 +01:00
|
|
|
if (show_none)
|
|
|
|
snprintf(p, rem, " (none)");
|
2024-10-05 07:46:00 -05:00
|
|
|
trace("%s.\n", buffer);
|
|
|
|
}
|
|
|
|
|
2024-08-01 19:13:31 -04:00
|
|
|
static void trace_format_cap(const struct shader_runner_caps *caps, enum format_cap cap, const char *cap_name)
|
|
|
|
{
|
|
|
|
bool show_none = true;
|
|
|
|
char buffer[80], *p;
|
|
|
|
size_t rem;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
rem = ARRAY_SIZE(buffer);
|
2024-10-05 07:46:00 -05:00
|
|
|
rc = snprintf(p, rem, "%8s:", cap_name);
|
2024-08-01 19:13:31 -04:00
|
|
|
p += rc;
|
|
|
|
rem -= rc;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < ARRAY_SIZE(caps->format_caps); ++i)
|
|
|
|
{
|
|
|
|
if (caps->format_caps[i] & cap)
|
|
|
|
{
|
|
|
|
rc = snprintf(p, rem, " 0x%x", i);
|
|
|
|
if (!(rc >= 0 && (size_t)rc < rem))
|
|
|
|
{
|
|
|
|
*p = 0;
|
|
|
|
trace("%s\n", buffer);
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
rem = ARRAY_SIZE(buffer);
|
2024-10-05 07:46:00 -05:00
|
|
|
rc = snprintf(p, rem, "%8s ", "");
|
2024-08-01 19:13:31 -04:00
|
|
|
--i;
|
|
|
|
}
|
|
|
|
p += rc;
|
|
|
|
rem -= rc;
|
|
|
|
show_none = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (show_none)
|
|
|
|
snprintf(p, rem, " (none)");
|
|
|
|
trace("%s.\n", buffer);
|
|
|
|
}
|
|
|
|
|
2024-04-04 12:44:27 -03:00
|
|
|
static void update_line_number_context(const char *testname, unsigned int line_number)
|
|
|
|
{
|
|
|
|
vkd3d_test_pop_context();
|
|
|
|
vkd3d_test_push_context("%s:%u", testname, line_number);
|
|
|
|
}
|
|
|
|
|
2024-08-05 12:58:23 -04:00
|
|
|
enum test_action
|
|
|
|
{
|
2024-12-10 19:17:56 -06:00
|
|
|
TEST_ACTION_COMPILE,
|
2024-08-05 12:58:23 -04:00
|
|
|
TEST_ACTION_RUN,
|
2024-08-16 23:23:14 -04:00
|
|
|
TEST_ACTION_SKIP_EXECUTION,
|
2024-08-05 12:58:23 -04:00
|
|
|
};
|
|
|
|
|
2024-02-19 16:47:11 +01:00
|
|
|
void run_shader_tests(struct shader_runner *runner, const struct shader_runner_caps *caps,
|
|
|
|
const struct shader_runner_ops *ops, void *dxc_compiler)
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2024-12-10 19:17:56 -06:00
|
|
|
enum test_action test_action = ops ? TEST_ACTION_RUN : TEST_ACTION_COMPILE;
|
2020-09-30 21:01:18 -05:00
|
|
|
size_t shader_source_size = 0, shader_source_len = 0;
|
2024-12-01 12:54:04 -06:00
|
|
|
enum shader_type shader_type = SHADER_TYPE_CS;
|
2022-03-21 20:42:17 -05:00
|
|
|
struct resource_params current_resource;
|
2021-11-05 19:35:49 +01:00
|
|
|
struct sampler *current_sampler = NULL;
|
2020-09-30 21:01:18 -05:00
|
|
|
enum parse_state state = STATE_NONE;
|
2024-04-04 12:44:27 -03:00
|
|
|
unsigned int i, line_number = 0, block_start_line_number = 0;
|
2020-09-30 21:01:18 -05:00
|
|
|
char *shader_source = NULL;
|
2023-09-14 19:18:58 +10:00
|
|
|
char line_buffer[256];
|
2023-12-07 10:26:34 -06:00
|
|
|
const char *testname;
|
2020-09-30 21:01:18 -05:00
|
|
|
FILE *f;
|
|
|
|
|
2024-02-19 17:01:00 +01:00
|
|
|
trace("Compiling SM%s-SM%s shaders with %s and executing with %s.\n",
|
|
|
|
model_strings[caps->minimum_shader_model], model_strings[caps->maximum_shader_model],
|
|
|
|
dxc_compiler ? "dxcompiler" : HLSL_COMPILER, caps->runner);
|
2024-03-19 12:36:23 +01:00
|
|
|
if (caps->tag_count)
|
|
|
|
trace_tags(caps);
|
2024-10-05 07:46:00 -05:00
|
|
|
trace_shader_caps(caps->shader_caps);
|
2024-08-01 19:13:31 -04:00
|
|
|
trace_format_cap(caps, FORMAT_CAP_UAV_LOAD, "uav-load");
|
2024-02-19 16:57:32 +01:00
|
|
|
|
2023-02-21 17:46:36 -06:00
|
|
|
if (!test_options.filename)
|
|
|
|
fatal_error("No filename specified.\n");
|
2020-09-30 21:01:18 -05:00
|
|
|
|
2023-02-21 17:46:36 -06:00
|
|
|
if (!(f = fopen(test_options.filename, "r")))
|
|
|
|
fatal_error("Unable to open '%s' for reading: %s\n", test_options.filename, strerror(errno));
|
2020-09-30 21:01:18 -05:00
|
|
|
|
2022-03-19 12:35:31 -05:00
|
|
|
memset(runner, 0, sizeof(*runner));
|
|
|
|
runner->ops = ops;
|
2024-03-19 12:36:23 +01:00
|
|
|
runner->caps = caps;
|
2024-10-24 15:57:43 -05:00
|
|
|
runner->dxc_compiler = dxc_compiler;
|
2024-02-19 16:47:11 +01:00
|
|
|
runner->minimum_shader_model = caps->minimum_shader_model;
|
|
|
|
runner->maximum_shader_model = caps->maximum_shader_model;
|
2024-05-17 19:53:12 -05:00
|
|
|
runner->alpha_test_func = VKD3D_SHADER_COMPARISON_FUNC_ALWAYS;
|
2024-10-03 16:23:04 -05:00
|
|
|
runner->point_size = 1.0f;
|
2024-10-03 17:55:33 -05:00
|
|
|
runner->point_size_min = 1.0f;
|
|
|
|
runner->point_size_max = FLT_MAX;
|
2024-10-05 10:26:20 -05:00
|
|
|
runner->fog_mode = FOG_MODE_DISABLE;
|
2024-11-13 19:16:39 -06:00
|
|
|
runner->fog_start = 0.0f;
|
|
|
|
runner->fog_end = 1.0f;
|
2024-11-13 19:39:35 -06:00
|
|
|
runner->fog_density = 1.0f;
|
2020-09-30 21:01:18 -05:00
|
|
|
|
2024-06-18 23:53:49 -05:00
|
|
|
runner->sample_mask = ~0u;
|
2024-08-31 18:54:44 +02:00
|
|
|
runner->depth_bounds = false;
|
|
|
|
runner->depth_min = 0.0f;
|
|
|
|
runner->depth_max = 1.0f;
|
2024-06-18 23:53:49 -05:00
|
|
|
|
2023-12-07 10:26:34 -06:00
|
|
|
if ((testname = strrchr(test_options.filename, '/')))
|
|
|
|
++testname;
|
|
|
|
else
|
|
|
|
testname = test_options.filename;
|
|
|
|
|
2024-04-04 12:44:27 -03:00
|
|
|
vkd3d_test_push_context("%s:%u", testname, line_number);
|
|
|
|
|
2020-10-03 16:24:26 -05:00
|
|
|
for (;;)
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2023-09-14 19:18:58 +10:00
|
|
|
char *ret = fgets(line_buffer, sizeof(line_buffer), f);
|
|
|
|
const char *line = line_buffer;
|
2020-09-30 21:01:22 -05:00
|
|
|
|
2024-04-04 12:44:27 -03:00
|
|
|
line_number++;
|
2020-10-03 16:24:26 -05:00
|
|
|
|
|
|
|
if (!ret || line[0] == '[')
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2024-04-04 12:44:27 -03:00
|
|
|
update_line_number_context(testname, block_start_line_number);
|
|
|
|
|
2020-09-30 21:01:18 -05:00
|
|
|
switch (state)
|
|
|
|
{
|
2022-03-21 20:42:16 -05:00
|
|
|
case STATE_INPUT_LAYOUT:
|
2020-09-30 21:01:18 -05:00
|
|
|
case STATE_NONE:
|
2021-11-05 19:35:49 +01:00
|
|
|
case STATE_SAMPLER:
|
2024-08-16 23:23:14 -04:00
|
|
|
break;
|
|
|
|
|
2020-09-30 21:01:18 -05:00
|
|
|
case STATE_TEST:
|
2024-12-19 12:40:03 +01:00
|
|
|
if (test_action == TEST_ACTION_SKIP_EXECUTION
|
|
|
|
&& runner->minimum_shader_model <= runner->maximum_shader_model)
|
2024-10-23 23:53:02 +02:00
|
|
|
skip("Missing capabilities.\n");
|
2022-01-26 19:40:29 -06:00
|
|
|
break;
|
|
|
|
|
2022-04-07 18:58:14 -05:00
|
|
|
case STATE_REQUIRE:
|
2024-12-10 19:17:56 -06:00
|
|
|
if (runner->maximum_shader_model < runner->minimum_shader_model
|
|
|
|
|| !check_capabilities(runner, caps))
|
2024-08-16 23:23:14 -04:00
|
|
|
test_action = TEST_ACTION_SKIP_EXECUTION;
|
2022-04-07 18:58:14 -05:00
|
|
|
break;
|
|
|
|
|
2022-06-08 18:18:35 -05:00
|
|
|
case STATE_RESOURCE:
|
2024-06-17 16:01:04 -05:00
|
|
|
if (current_resource.desc.type == RESOURCE_TYPE_VERTEX_BUFFER)
|
|
|
|
current_resource.desc.width = current_resource.data_size;
|
2024-06-17 15:39:38 -05:00
|
|
|
|
2024-07-31 21:48:19 -04:00
|
|
|
if (current_resource.desc.type == RESOURCE_TYPE_UAV)
|
|
|
|
assert_that(current_resource.explicit_format, "Format must be specified for UAV resources.\n");
|
|
|
|
|
2023-10-17 12:01:01 +02:00
|
|
|
/* Not every backend supports every resource type
|
|
|
|
* (specifically, D3D9 doesn't support UAVs and
|
|
|
|
* textures with data type other than float). */
|
2024-08-05 12:58:23 -04:00
|
|
|
if (test_action == TEST_ACTION_RUN)
|
2024-04-10 13:51:06 +10:00
|
|
|
set_resource(runner, ¤t_resource);
|
2022-03-21 20:42:17 -05:00
|
|
|
free(current_resource.data);
|
2020-09-30 21:01:18 -05:00
|
|
|
break;
|
|
|
|
|
2024-12-01 12:54:04 -06:00
|
|
|
case STATE_SHADER:
|
2024-12-10 19:17:56 -06:00
|
|
|
if (test_action == TEST_ACTION_COMPILE)
|
|
|
|
{
|
|
|
|
/* Most versions have relatively minor differences
|
|
|
|
* between them, so don't waste time testing every
|
|
|
|
* version possible.
|
|
|
|
* SM1-3, SM4-5, and SM6 are completely different
|
|
|
|
* formats, often with different HLSL semantics, so
|
|
|
|
* where possible try to test one version from each set. */
|
|
|
|
|
2024-12-11 23:15:59 -06:00
|
|
|
static const uint32_t sm1_mask = (1u << SHADER_MODEL_4_0) - 1;
|
|
|
|
static const uint32_t sm4_mask = ((1u << SHADER_MODEL_6_0) - 1) & ~sm1_mask;
|
|
|
|
|
2024-12-10 19:17:56 -06:00
|
|
|
uint32_t model_mask = 0;
|
|
|
|
|
2024-12-11 23:15:59 -06:00
|
|
|
if (runner->hlsl_hrs[runner->minimum_shader_model] == S_OK)
|
|
|
|
bitmap_set(&model_mask, runner->minimum_shader_model);
|
|
|
|
for (unsigned int j = SHADER_MODEL_MIN + 1; j <= SHADER_MODEL_MAX; ++j)
|
|
|
|
{
|
|
|
|
if (runner->hlsl_hrs[j - 1] != runner->hlsl_hrs[j])
|
|
|
|
{
|
|
|
|
/* Behaviour changes here; test both versions. */
|
|
|
|
bitmap_set(&model_mask, j - 1);
|
|
|
|
bitmap_set(&model_mask, j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(model_mask & sm1_mask) && runner->minimum_shader_model <= SHADER_MODEL_3_0)
|
2024-12-10 19:17:56 -06:00
|
|
|
bitmap_set(&model_mask, runner->minimum_shader_model);
|
2024-12-11 23:15:59 -06:00
|
|
|
if (!(model_mask & sm4_mask)
|
|
|
|
&& runner->minimum_shader_model <= SHADER_MODEL_5_1
|
2024-12-10 19:17:56 -06:00
|
|
|
&& runner->maximum_shader_model >= SHADER_MODEL_4_0)
|
|
|
|
bitmap_set(&model_mask, max(runner->minimum_shader_model, SHADER_MODEL_4_0));
|
|
|
|
if (runner->maximum_shader_model >= SHADER_MODEL_6_0)
|
|
|
|
bitmap_set(&model_mask, max(runner->minimum_shader_model, SHADER_MODEL_6_0));
|
|
|
|
|
2024-12-11 23:15:59 -06:00
|
|
|
for (enum shader_model model = runner->minimum_shader_model;
|
|
|
|
model <= runner->maximum_shader_model; ++model)
|
2024-12-10 19:17:56 -06:00
|
|
|
{
|
|
|
|
if (!bitmap_is_set(&model_mask, model))
|
|
|
|
continue;
|
|
|
|
vkd3d_test_push_context("Model %s", model_strings[model]);
|
|
|
|
compile_shader(runner, shader_source, shader_source_len, shader_type, model);
|
|
|
|
vkd3d_test_pop_context();
|
|
|
|
}
|
|
|
|
}
|
2024-12-01 12:54:04 -06:00
|
|
|
free(runner->shader_source[shader_type]);
|
|
|
|
runner->shader_source[shader_type] = shader_source;
|
2024-04-19 12:33:56 +10:00
|
|
|
shader_source = NULL;
|
|
|
|
shader_source_len = 0;
|
|
|
|
shader_source_size = 0;
|
|
|
|
break;
|
|
|
|
|
2020-11-24 00:29:57 -06:00
|
|
|
case STATE_PREPROC_INVALID:
|
|
|
|
{
|
|
|
|
ID3D10Blob *blob = NULL, *errors = NULL;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2024-12-10 19:17:56 -06:00
|
|
|
if (test_action != TEST_ACTION_COMPILE)
|
2023-09-21 11:54:27 +10:00
|
|
|
break;
|
|
|
|
|
2020-11-24 00:29:57 -06:00
|
|
|
hr = D3DPreprocess(shader_source, strlen(shader_source), NULL, NULL, NULL, &blob, &errors);
|
|
|
|
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
|
|
|
|
ok(!blob, "Expected no compiled shader blob.\n");
|
|
|
|
ok(!!errors, "Expected non-NULL error blob.\n");
|
|
|
|
|
|
|
|
if (errors)
|
|
|
|
{
|
|
|
|
if (vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
|
|
|
|
ID3D10Blob_Release(errors);
|
|
|
|
}
|
|
|
|
|
|
|
|
shader_source_len = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-21 17:23:45 -06:00
|
|
|
case STATE_PREPROC:
|
|
|
|
{
|
|
|
|
ID3D10Blob *blob = NULL, *errors = NULL;
|
2020-12-01 20:51:08 -06:00
|
|
|
SIZE_T size;
|
2020-11-21 17:23:45 -06:00
|
|
|
HRESULT hr;
|
|
|
|
char *text;
|
|
|
|
|
2024-12-10 19:17:56 -06:00
|
|
|
if (test_action != TEST_ACTION_COMPILE)
|
2023-09-21 11:54:27 +10:00
|
|
|
break;
|
|
|
|
|
2020-11-21 17:23:45 -06:00
|
|
|
hr = D3DPreprocess(shader_source, strlen(shader_source), NULL, NULL, NULL, &blob, &errors);
|
|
|
|
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
|
|
|
|
if (hr == S_OK)
|
|
|
|
{
|
|
|
|
if (errors)
|
|
|
|
{
|
|
|
|
if (vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
|
|
|
|
ID3D10Blob_Release(errors);
|
|
|
|
}
|
|
|
|
|
|
|
|
text = ID3D10Blob_GetBufferPointer(blob);
|
2020-12-01 20:51:08 -06:00
|
|
|
size = ID3D10Blob_GetBufferSize(blob);
|
|
|
|
ok(vkd3d_memmem(text, size, "pass", strlen("pass")),
|
|
|
|
"'pass' not found in preprocessed shader.\n");
|
|
|
|
ok(!vkd3d_memmem(text, size, "fail", strlen("fail")),
|
|
|
|
"'fail' found in preprocessed shader.\n");
|
2020-11-21 17:23:45 -06:00
|
|
|
ID3D10Blob_Release(blob);
|
|
|
|
}
|
|
|
|
|
|
|
|
shader_source_len = 0;
|
|
|
|
break;
|
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
2023-04-17 14:53:24 +02:00
|
|
|
|
2023-04-12 11:34:42 -05:00
|
|
|
if (!ret)
|
|
|
|
break;
|
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
|
2020-10-03 16:24:26 -05:00
|
|
|
if (line[0] == '[')
|
|
|
|
{
|
2021-10-03 19:19:08 -05:00
|
|
|
unsigned int index;
|
|
|
|
|
2024-04-04 12:44:27 -03:00
|
|
|
block_start_line_number = line_number;
|
|
|
|
update_line_number_context(testname, line_number);
|
|
|
|
|
2024-12-10 18:10:59 -06:00
|
|
|
if (match_string(line, "[compute shader", &line))
|
2021-08-13 16:37:31 -05:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_CS;
|
2021-08-16 12:25:41 -05:00
|
|
|
}
|
2021-08-13 16:37:31 -05:00
|
|
|
else if (!strcmp(line, "[require]\n"))
|
2022-01-26 15:35:33 +01:00
|
|
|
{
|
|
|
|
state = STATE_REQUIRE;
|
2024-02-19 16:47:11 +01:00
|
|
|
runner->minimum_shader_model = caps->minimum_shader_model;
|
|
|
|
runner->maximum_shader_model = caps->maximum_shader_model;
|
2024-10-05 07:46:00 -05:00
|
|
|
memset(runner->require_shader_caps, 0, sizeof(runner->require_shader_caps));
|
2024-08-01 19:13:31 -04:00
|
|
|
memset(runner->require_format_caps, 0, sizeof(runner->require_format_caps));
|
2023-09-21 11:54:27 +10:00
|
|
|
runner->compile_options = 0;
|
2024-12-10 19:17:56 -06:00
|
|
|
test_action = ops ? TEST_ACTION_RUN : TEST_ACTION_COMPILE;
|
2022-01-26 15:35:33 +01:00
|
|
|
}
|
2024-12-10 18:10:59 -06:00
|
|
|
else if (match_string(line, "[pixel shader", &line))
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_PS;
|
2021-09-11 11:20:32 -05:00
|
|
|
}
|
2021-11-05 19:35:49 +01:00
|
|
|
else if (sscanf(line, "[sampler %u]\n", &index))
|
|
|
|
{
|
|
|
|
state = STATE_SAMPLER;
|
|
|
|
|
2023-09-22 07:31:31 +02:00
|
|
|
if (!(current_sampler = shader_runner_get_sampler(runner, index)))
|
2021-11-05 19:35:49 +01:00
|
|
|
{
|
2022-04-11 12:18:30 -05:00
|
|
|
if (runner->sampler_count == MAX_SAMPLERS)
|
|
|
|
fatal_error("Too many samplers declared.\n");
|
|
|
|
|
|
|
|
current_sampler = &runner->samplers[runner->sampler_count++];
|
2021-11-05 19:35:49 +01:00
|
|
|
}
|
2022-04-11 12:18:30 -05:00
|
|
|
memset(current_sampler, 0, sizeof(*current_sampler));
|
2021-11-05 19:35:49 +01:00
|
|
|
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;
|
|
|
|
}
|
2024-01-24 16:11:17 -03:00
|
|
|
else if (sscanf(line, "[rtv %u]\n", &index))
|
2022-06-08 18:18:39 -05:00
|
|
|
{
|
|
|
|
state = STATE_RESOURCE;
|
|
|
|
|
|
|
|
memset(¤t_resource, 0, sizeof(current_resource));
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.slot = index;
|
|
|
|
current_resource.desc.type = RESOURCE_TYPE_RENDER_TARGET;
|
|
|
|
current_resource.desc.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
2022-06-08 18:18:39 -05:00
|
|
|
current_resource.data_type = TEXTURE_DATA_FLOAT;
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.texel_size = 16;
|
|
|
|
current_resource.desc.level_count = 1;
|
2022-06-08 18:18:39 -05:00
|
|
|
}
|
2024-04-15 10:33:15 +10:00
|
|
|
else if (!strcmp(line, "[dsv]\n"))
|
|
|
|
{
|
|
|
|
state = STATE_RESOURCE;
|
|
|
|
|
|
|
|
memset(¤t_resource, 0, sizeof(current_resource));
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.slot = 0;
|
|
|
|
current_resource.desc.type = RESOURCE_TYPE_DEPTH_STENCIL;
|
|
|
|
current_resource.desc.format = DXGI_FORMAT_D32_FLOAT;
|
2024-04-15 10:33:15 +10:00
|
|
|
current_resource.is_shadow = true;
|
|
|
|
current_resource.data_type = TEXTURE_DATA_FLOAT;
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.texel_size = 4;
|
|
|
|
current_resource.desc.level_count = 1;
|
2024-04-15 10:33:15 +10:00
|
|
|
}
|
2024-01-24 16:11:17 -03:00
|
|
|
else if (sscanf(line, "[srv %u]\n", &index))
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2022-06-08 18:18:35 -05:00
|
|
|
state = STATE_RESOURCE;
|
2021-10-03 19:19:08 -05:00
|
|
|
|
2022-03-21 20:42:17 -05:00
|
|
|
memset(¤t_resource, 0, sizeof(current_resource));
|
2022-01-26 19:40:29 -06:00
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.slot = index;
|
|
|
|
current_resource.desc.type = RESOURCE_TYPE_TEXTURE;
|
|
|
|
current_resource.desc.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
2022-03-21 20:42:17 -05:00
|
|
|
current_resource.data_type = TEXTURE_DATA_FLOAT;
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.texel_size = 16;
|
|
|
|
current_resource.desc.level_count = 1;
|
2021-10-03 19:19:08 -05:00
|
|
|
}
|
2022-06-08 18:18:35 -05:00
|
|
|
else if (sscanf(line, "[uav %u]\n", &index))
|
|
|
|
{
|
|
|
|
state = STATE_RESOURCE;
|
|
|
|
|
|
|
|
memset(¤t_resource, 0, sizeof(current_resource));
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.slot = index;
|
|
|
|
current_resource.desc.type = RESOURCE_TYPE_UAV;
|
|
|
|
current_resource.desc.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
2023-05-09 19:56:55 +02:00
|
|
|
current_resource.data_type = TEXTURE_DATA_FLOAT;
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.texel_size = 16;
|
|
|
|
current_resource.desc.level_count = 1;
|
2023-05-09 19:56:55 +02:00
|
|
|
}
|
2024-01-24 16:11:17 -03:00
|
|
|
else if (sscanf(line, "[vb %u]\n", &index))
|
2022-03-21 20:42:18 -05:00
|
|
|
{
|
2022-06-08 18:18:35 -05:00
|
|
|
state = STATE_RESOURCE;
|
2022-03-21 20:42:18 -05:00
|
|
|
|
|
|
|
memset(¤t_resource, 0, sizeof(current_resource));
|
|
|
|
|
2024-06-17 16:01:04 -05:00
|
|
|
current_resource.desc.slot = index;
|
|
|
|
current_resource.desc.type = RESOURCE_TYPE_VERTEX_BUFFER;
|
|
|
|
current_resource.desc.dimension = RESOURCE_DIMENSION_BUFFER;
|
2022-03-21 20:42:18 -05:00
|
|
|
current_resource.data_type = TEXTURE_DATA_FLOAT;
|
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
else if (!strcmp(line, "[test]\n"))
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2020-09-30 21:01:18 -05:00
|
|
|
state = STATE_TEST;
|
2021-10-03 19:19:08 -05:00
|
|
|
}
|
2020-11-21 17:23:45 -06:00
|
|
|
else if (!strcmp(line, "[preproc]\n"))
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2020-11-21 17:23:45 -06:00
|
|
|
state = STATE_PREPROC;
|
2021-10-03 19:19:08 -05:00
|
|
|
}
|
2020-11-24 00:29:57 -06:00
|
|
|
else if (!strcmp(line, "[preproc fail]\n"))
|
2021-10-03 19:19:08 -05:00
|
|
|
{
|
2020-11-24 00:29:57 -06:00
|
|
|
state = STATE_PREPROC_INVALID;
|
2021-10-03 19:19:08 -05:00
|
|
|
}
|
2024-12-10 18:10:59 -06:00
|
|
|
else if (match_string(line, "[vertex shader", &line))
|
2022-03-21 20:42:14 -05:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_VS;
|
2023-04-04 19:23:26 -04:00
|
|
|
}
|
2024-12-10 18:10:59 -06:00
|
|
|
else if (match_string(line, "[effect", &line))
|
2023-10-12 12:51:19 +02:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_FX;
|
2023-10-12 12:51:19 +02:00
|
|
|
}
|
2024-12-10 18:10:59 -06:00
|
|
|
else if (match_string(line, "[hull shader", &line))
|
2024-04-08 14:37:32 +10:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_HS;
|
2024-04-08 14:37:32 +10:00
|
|
|
}
|
2024-12-10 18:10:59 -06:00
|
|
|
else if (match_string(line, "[domain shader", &line))
|
2024-04-08 14:37:32 +10:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_DS;
|
2024-04-08 14:37:32 +10:00
|
|
|
}
|
2024-12-10 18:10:59 -06:00
|
|
|
else if (match_string(line, "[geometry shader", &line))
|
2024-04-19 12:33:56 +10:00
|
|
|
{
|
2024-12-01 12:54:04 -06:00
|
|
|
state = STATE_SHADER;
|
|
|
|
shader_type = SHADER_TYPE_GS;
|
2024-04-19 12:33:56 +10:00
|
|
|
}
|
2022-03-21 20:42:16 -05:00
|
|
|
else if (!strcmp(line, "[input layout]\n"))
|
|
|
|
{
|
|
|
|
state = STATE_INPUT_LAYOUT;
|
|
|
|
|
|
|
|
for (i = 0; i < runner->input_element_count; ++i)
|
|
|
|
free(runner->input_elements[i].name);
|
|
|
|
runner->input_element_count = 0;
|
|
|
|
}
|
2024-12-01 12:54:04 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fatal_error("Unknown directive '%s'.\n", line);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == STATE_SHADER)
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
read_shader_directive(runner, line_buffer, line);
|
2020-09-30 21:01:18 -05:00
|
|
|
}
|
2021-10-03 19:19:07 -05:00
|
|
|
else if (line[0] != '%' && line[0] != '\n')
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
2024-04-04 12:44:27 -03:00
|
|
|
update_line_number_context(testname, line_number);
|
|
|
|
|
2020-09-30 21:01:18 -05:00
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case STATE_NONE:
|
2021-11-05 19:35:50 +01:00
|
|
|
fatal_error("Malformed line '%s'.\n", line);
|
2020-09-30 21:01:18 -05:00
|
|
|
break;
|
|
|
|
|
2022-03-21 20:42:16 -05:00
|
|
|
case STATE_INPUT_LAYOUT:
|
|
|
|
parse_input_layout_directive(runner, line);
|
|
|
|
break;
|
|
|
|
|
2020-11-21 17:23:45 -06:00
|
|
|
case STATE_PREPROC:
|
2020-11-24 00:29:57 -06:00
|
|
|
case STATE_PREPROC_INVALID:
|
2024-12-01 12:54:04 -06:00
|
|
|
case STATE_SHADER:
|
2020-09-30 21:01:18 -05:00
|
|
|
{
|
|
|
|
size_t len = strlen(line);
|
|
|
|
|
|
|
|
vkd3d_array_reserve((void **)&shader_source, &shader_source_size, shader_source_len + len + 1, 1);
|
|
|
|
memcpy(shader_source + shader_source_len, line, len + 1);
|
|
|
|
shader_source_len += len;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-01-26 15:35:33 +01:00
|
|
|
case STATE_REQUIRE:
|
2022-03-19 12:35:31 -05:00
|
|
|
parse_require_directive(runner, line);
|
2022-01-26 15:35:33 +01:00
|
|
|
break;
|
|
|
|
|
2022-06-08 18:18:35 -05:00
|
|
|
case STATE_RESOURCE:
|
|
|
|
parse_resource_directive(¤t_resource, line);
|
2021-11-05 19:35:49 +01:00
|
|
|
break;
|
|
|
|
|
2022-06-08 18:18:35 -05:00
|
|
|
case STATE_SAMPLER:
|
|
|
|
parse_sampler_directive(current_sampler, line);
|
2021-10-03 19:19:08 -05:00
|
|
|
break;
|
|
|
|
|
2020-09-30 21:01:18 -05:00
|
|
|
case STATE_TEST:
|
2023-09-14 19:29:24 +10:00
|
|
|
/* Compilation which fails with dxcompiler is not 'todo', therefore the tests are
|
|
|
|
* not 'todo' either. They cannot run, so skip them entirely. */
|
tests/shader_runner: Record HLSL todo/fail state for each shader model.
When a shader fails to compile for a range of versions, we want to validate that
we are correctly implementing that behaviour. E.g. if a feature requires shader
model 5.0, we should validate that it compiles correctly with 5.0 (which we do),
but also that it *fails* to compile with 4.1 (which we do not).
The obvious and simple solution is to simply run compile tests for each version.
There are, however, at least 12 versions of HLSL up to and including 6.0, at
least 10 of which are known to introduce new features. Shader compilation takes
about 10-15% of the time that draw and dispatch does, both for native and
(currently) vkd3d. Testing every version for every shader would add a
noticeable amount of time to the tests.
In practice, the interesting versions to test for most shaders are:
* At least one from each range 1-3, 4-5, and 6. It's common enough for the
semantics of the HLSL to differ between bytecode formats, or for features to
be added or removed across those boundaries.
* If the shader requires a given feature, we want to test both sides of the cusp
to ensure we're requiring the same version for the feature.
In practice this is 3 or 4 versions, which is measurably less than the 12 we'd
otherwise be running.
In order to achieve this goal of testing only the 3 or 4 interesting versions
for a shader, we need to know what version is actually required for a feature.
This is encoded in the shader itself using e.g. [pixel shader fail(sm<5)].
This patch therefore implements the first step towards this goal, namely,
determining which versions succeed and fail, so we can figure out which ones are
interesting.
We could require the test writer to specify which versions are interesting ahead
of time (e.g. "for version in 2.0 4.1 5.0 6.0") but this is both redundant (and
there are a *lot* of tests that need some feature gate) and easy for a test
writer to get wrong by missing interesting versions.
2024-12-10 18:47:48 -06:00
|
|
|
if (!runner->failed_resource_count && test_action == TEST_ACTION_RUN
|
|
|
|
&& SUCCEEDED(runner->hlsl_hrs[runner->minimum_shader_model]))
|
2023-09-21 11:54:27 +10:00
|
|
|
parse_test_directive(runner, line);
|
2020-09-30 21:01:18 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-04 12:44:27 -03:00
|
|
|
/* Pop line_number context. */
|
|
|
|
vkd3d_test_pop_context();
|
2023-12-07 10:26:34 -06:00
|
|
|
|
2022-03-21 20:42:16 -05:00
|
|
|
for (i = 0; i < runner->input_element_count; ++i)
|
|
|
|
free(runner->input_elements[i].name);
|
|
|
|
free(runner->input_elements);
|
2023-10-27 11:11:57 -05:00
|
|
|
for (i = 0; i < SHADER_TYPE_COUNT; ++i)
|
|
|
|
free(runner->shader_source[i]);
|
2024-01-24 18:53:35 -03:00
|
|
|
free(runner->uniforms);
|
2022-03-21 20:42:17 -05:00
|
|
|
for (i = 0; i < runner->resource_count; ++i)
|
2022-01-26 19:40:29 -06:00
|
|
|
{
|
2022-03-21 20:42:17 -05:00
|
|
|
if (runner->resources[i])
|
|
|
|
runner->ops->destroy_resource(runner, runner->resources[i]);
|
2022-01-26 19:40:29 -06:00
|
|
|
}
|
2020-09-30 21:01:18 -05:00
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
}
|
2022-01-26 19:40:27 -06:00
|
|
|
|
2023-01-18 14:30:47 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
static void print_dll_version(const char *file_name)
|
|
|
|
{
|
|
|
|
BOOL (WINAPI *GetFileVersionInfoA)(const char *, DWORD, DWORD, void *);
|
|
|
|
BOOL (WINAPI *VerQueryValueA)(void *, char *, void **, UINT*);
|
|
|
|
DWORD (WINAPI *GetFileVersionInfoSizeA)(const char *, DWORD *);
|
|
|
|
HMODULE version_module;
|
|
|
|
DWORD size, handle;
|
|
|
|
bool done = false;
|
|
|
|
|
|
|
|
version_module = LoadLibraryA("version.dll");
|
|
|
|
if (!version_module)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
#define X(name) name = (void *)GetProcAddress(version_module, #name);
|
|
|
|
X(GetFileVersionInfoSizeA);
|
|
|
|
X(GetFileVersionInfoA);
|
|
|
|
X(VerQueryValueA);
|
|
|
|
#undef X
|
|
|
|
|
|
|
|
if (!GetFileVersionInfoSizeA || !GetFileVersionInfoA || !VerQueryValueA)
|
|
|
|
{
|
|
|
|
FreeLibrary(version_module);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = GetFileVersionInfoSizeA(file_name, &handle);
|
|
|
|
if (size)
|
|
|
|
{
|
|
|
|
char *data = malloc(size);
|
|
|
|
|
|
|
|
if (GetFileVersionInfoA(file_name, handle, size, data))
|
|
|
|
{
|
|
|
|
VS_FIXEDFILEINFO *info;
|
|
|
|
UINT len;
|
|
|
|
|
|
|
|
if (VerQueryValueA(data, "\\", (void **)&info, &len))
|
|
|
|
{
|
|
|
|
trace("%s version: %lu.%lu.%lu.%lu\n", file_name,
|
|
|
|
info->dwFileVersionMS >> 16, info->dwFileVersionMS & 0xffff,
|
|
|
|
info->dwFileVersionLS >> 16, info->dwFileVersionLS & 0xffff);
|
|
|
|
done = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeLibrary(version_module);
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (!done)
|
|
|
|
trace("%s version: unknown\n", file_name);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-12-10 19:17:56 -06:00
|
|
|
static void run_compile_tests(void *dxc_compiler)
|
|
|
|
{
|
|
|
|
struct shader_runner_caps caps = {0};
|
|
|
|
struct shader_runner runner = {0};
|
|
|
|
|
|
|
|
caps.runner = "hlsl";
|
|
|
|
caps.minimum_shader_model = SHADER_MODEL_MIN;
|
|
|
|
caps.maximum_shader_model = dxc_compiler ? SHADER_MODEL_MAX : SHADER_MODEL_5_1;
|
|
|
|
for (unsigned int i = 0; i < SHADER_CAP_COUNT; ++i)
|
|
|
|
caps.shader_caps[i] = true;
|
|
|
|
for (unsigned int i = 0; i < DXGI_FORMAT_COUNT; ++i)
|
|
|
|
caps.format_caps[i] = ~0u;
|
|
|
|
|
|
|
|
run_shader_tests(&runner, &caps, NULL, dxc_compiler);
|
|
|
|
}
|
|
|
|
|
2022-01-26 19:40:27 -06:00
|
|
|
START_TEST(shader_runner)
|
|
|
|
{
|
2024-11-06 15:11:30 +01:00
|
|
|
IDxcCompiler3 *dxc;
|
2023-09-14 19:29:24 +10:00
|
|
|
|
2023-02-21 17:46:36 -06:00
|
|
|
parse_args(argc, argv);
|
|
|
|
|
2024-11-06 15:11:30 +01:00
|
|
|
dxc = dxcompiler_create();
|
|
|
|
|
2024-12-10 19:17:56 -06:00
|
|
|
trace("Running HLSL compile tests.\n");
|
|
|
|
run_compile_tests(dxc);
|
|
|
|
|
2023-01-18 14:30:47 +01:00
|
|
|
#if defined(VKD3D_CROSSTEST)
|
|
|
|
trace("Running tests from a Windows cross build\n");
|
|
|
|
|
2023-02-21 17:46:36 -06:00
|
|
|
run_shader_tests_d3d9();
|
|
|
|
run_shader_tests_d3d11();
|
2024-11-06 15:11:30 +01:00
|
|
|
run_shader_tests_d3d12(dxc);
|
2023-01-18 14:30:47 +01:00
|
|
|
|
2024-11-06 15:11:30 +01:00
|
|
|
if (dxc)
|
2024-02-23 13:58:02 +01:00
|
|
|
print_dll_version("dxcompiler.dll");
|
2023-01-18 14:30:47 +01:00
|
|
|
print_dll_version("d3dcompiler_47.dll");
|
|
|
|
print_dll_version("dxgi.dll");
|
|
|
|
print_dll_version("d3d9.dll");
|
|
|
|
print_dll_version("d3d11.dll");
|
|
|
|
print_dll_version("d3d12.dll");
|
2024-05-02 11:56:04 -07:00
|
|
|
print_dll_version("d3d12core.dll");
|
2024-10-03 22:21:07 +02:00
|
|
|
print_dll_version("d3d10warp.dll");
|
2024-05-02 11:56:04 -07:00
|
|
|
if (test_options.enable_debug_layer)
|
|
|
|
print_dll_version("d3d12sdklayers.dll");
|
2023-12-14 03:08:41 -03:00
|
|
|
|
2023-01-18 14:30:47 +01:00
|
|
|
#elif defined(_WIN32)
|
|
|
|
trace("Running tests from a Windows non-cross build\n");
|
|
|
|
|
2023-02-21 17:46:36 -06:00
|
|
|
run_shader_tests_d3d9();
|
|
|
|
run_shader_tests_d3d11();
|
2024-11-06 15:11:30 +01:00
|
|
|
run_shader_tests_d3d12(dxc);
|
2023-01-18 14:30:47 +01:00
|
|
|
|
2024-11-06 15:11:30 +01:00
|
|
|
if (dxc)
|
2023-09-14 19:29:24 +10:00
|
|
|
print_dll_version(SONAME_LIBDXCOMPILER);
|
2023-01-18 14:30:47 +01:00
|
|
|
print_dll_version("d3d9.dll");
|
|
|
|
print_dll_version("d3d11.dll");
|
2023-12-14 03:08:41 -03:00
|
|
|
|
2022-04-11 12:18:31 -05:00
|
|
|
#else
|
2023-01-18 14:30:47 +01:00
|
|
|
trace("Running tests from a Unix build\n");
|
|
|
|
|
2023-09-22 07:31:31 +02:00
|
|
|
# ifdef HAVE_OPENGL
|
|
|
|
run_shader_tests_gl();
|
|
|
|
# endif
|
2024-10-21 22:23:27 +08:00
|
|
|
# ifdef HAVE_METAL
|
|
|
|
run_shader_tests_metal();
|
|
|
|
# endif
|
2023-02-21 17:46:36 -06:00
|
|
|
run_shader_tests_vulkan();
|
2024-11-06 15:11:30 +01:00
|
|
|
run_shader_tests_d3d12(dxc);
|
2023-01-18 14:30:47 +01:00
|
|
|
#endif
|
2024-11-06 15:11:30 +01:00
|
|
|
|
|
|
|
if (dxc)
|
|
|
|
IDxcCompiler3_Release(dxc);
|
2022-01-26 19:40:27 -06:00
|
|
|
}
|