Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH vkd3d v6 5/9] tests: Add a test for multiple render targets.
by Zebediah Figura
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
Makefile.am | 1 +
tests/multiple-rt.shader_test | 19 +++++++++++++++++++
tests/shader_runner.c | 26 ++++++++++++++++++++++++--
3 files changed, 44 insertions(+), 2 deletions(-)
create mode 100644 tests/multiple-rt.shader_test
diff --git a/Makefile.am b/Makefile.am
index 400dc8aae..6e827175a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -108,6 +108,7 @@ vkd3d_shader_tests = \
tests/hlsl-vector-indexing-uniform.shader_test \
tests/logic-operations.shader_test \
tests/math.shader_test \
+ tests/multiple-rt.shader_test \
tests/nointerpolation.shader_test \
tests/pow.shader_test \
tests/preproc-if.shader_test \
diff --git a/tests/multiple-rt.shader_test b/tests/multiple-rt.shader_test
new file mode 100644
index 000000000..59e4acbbe
--- /dev/null
+++ b/tests/multiple-rt.shader_test
@@ -0,0 +1,19 @@
+[render target 0]
+format r32g32b32a32 float
+size (640, 480)
+
+[render target 1]
+format r32g32b32a32 float
+size (640, 480)
+
+[pixel shader]
+void main(out float4 o0 : sv_target0, out float4 o1 : sv_target1)
+{
+ o0 = float4(0.1, 0.2, 0.3, 0.4);
+ o1 = float4(0.5, 0.6, 0.7, 0.8);
+}
+
+[test]
+draw quad
+probe render target 0 all rgba (0.1, 0.2, 0.3, 0.4)
+probe render target 1 all rgba (0.5, 0.6, 0.7, 0.8)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c
index e2dc2dda6..25986b316 100644
--- a/tests/shader_runner.c
+++ b/tests/shader_runner.c
@@ -468,7 +468,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
}
else if (match_string(line, "probe", &line))
{
- unsigned int left, top, right, bottom, ulps;
+ unsigned int left, top, right, bottom, ulps, slot;
struct resource_readback *rb;
struct resource *resource;
int ret, len;
@@ -479,7 +479,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
if (match_string(line, "uav", &line))
{
- unsigned int slot = strtoul(line, &rest, 10);
+ slot = strtoul(line, &rest, 10);
if (rest == line)
fatal_error("Malformed UAV index '%s'.\n", line);
@@ -487,6 +487,16 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
resource = get_resource(runner, RESOURCE_TYPE_UAV, slot);
}
+ else if (match_string(line, "render target", &line))
+ {
+ slot = strtoul(line, &rest, 10);
+
+ if (rest == line)
+ fatal_error("Malformed render target index '%s'.\n", line);
+ line = rest;
+
+ resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, slot);
+ }
else
{
resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0);
@@ -836,6 +846,18 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
current_sampler->v_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
current_sampler->w_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
}
+ else if (sscanf(line, "[render target %u]\n", &index))
+ {
+ state = STATE_RESOURCE;
+
+ memset(¤t_resource, 0, sizeof(current_resource));
+
+ current_resource.slot = index;
+ current_resource.type = RESOURCE_TYPE_RENDER_TARGET;
+ current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ current_resource.data_type = TEXTURE_DATA_FLOAT;
+ current_resource.texel_size = 16;
+ }
else if (sscanf(line, "[texture %u]\n", &index))
{
state = STATE_RESOURCE;
--
2.36.1
June 8, 2022
[PATCH vkd3d v6 4/9] tests: Add a basic shader test for UAVs.
by Zebediah Figura
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
Makefile.am | 1 +
tests/shader_runner.c | 22 ++++++++++++--
tests/shader_runner_d3d12.c | 10 +++++--
tests/shader_runner_vulkan.c | 12 ++++----
tests/uav.shader_test | 56 ++++++++++++++++++++++++++++++++++++
5 files changed, 90 insertions(+), 11 deletions(-)
create mode 100644 tests/uav.shader_test
diff --git a/Makefile.am b/Makefile.am
index dd3ce1ff6..400dc8aae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,6 +132,7 @@ vkd3d_shader_tests = \
tests/texture-load.shader_test \
tests/texture-load-typed.shader_test \
tests/trigonometry.shader_test \
+ tests/uav.shader_test \
tests/writemask-assignop-0.shader_test \
tests/writemask-assignop-1.shader_test \
tests/writemask-assignop-2.shader_test \
diff --git a/tests/shader_runner.c b/tests/shader_runner.c
index f367027f7..e2dc2dda6 100644
--- a/tests/shader_runner.c
+++ b/tests/shader_runner.c
@@ -370,6 +370,8 @@ static void set_uniforms(struct shader_runner *runner, size_t offset, size_t cou
static void parse_test_directive(struct shader_runner *runner, const char *line)
{
+ char *rest;
+
runner->is_todo = false;
if (match_string(line, "todo", &line))
@@ -475,19 +477,33 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
if (runner->last_render_failed)
return;
- resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0);
+ if (match_string(line, "uav", &line))
+ {
+ unsigned int slot = strtoul(line, &rest, 10);
+
+ if (rest == line)
+ fatal_error("Malformed UAV index '%s'.\n", line);
+ line = rest;
+
+ resource = get_resource(runner, RESOURCE_TYPE_UAV, slot);
+ }
+ else
+ {
+ resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0);
+ }
+
rb = runner->ops->get_resource_readback(runner, resource);
if (match_string(line, "all", &line))
{
set_rect(&rect, 0, 0, resource->width, resource->height);
}
- else if (sscanf(line, "( %d , %d , %d , %d )%n", &left, &top, &right, &bottom, &len) == 4)
+ else if (sscanf(line, " ( %d , %d , %d , %d )%n", &left, &top, &right, &bottom, &len) == 4)
{
set_rect(&rect, left, top, right, bottom);
line += len;
}
- else if (sscanf(line, "( %u , %u )%n", &left, &top, &len) == 2)
+ else if (sscanf(line, " ( %u , %u )%n", &left, &top, &len) == 2)
{
set_rect(&rect, left, top, left + 1, top + 1);
line += len;
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index 79d5b8ebb..871b50222 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -373,16 +373,20 @@ static struct resource_readback *d3d12_runner_get_resource_readback(struct shade
struct test_context *test_context = &runner->test_context;
struct d3d12_resource_readback *rb = malloc(sizeof(*rb));
struct d3d12_resource *resource = d3d12_resource(res);
+ D3D12_RESOURCE_STATES state;
- assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET);
+ if (resource->r.type == RESOURCE_TYPE_RENDER_TARGET)
+ state = D3D12_RESOURCE_STATE_RENDER_TARGET;
+ else
+ state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
transition_resource_state(test_context->list, resource->resource,
- D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ state, D3D12_RESOURCE_STATE_COPY_SOURCE);
get_texture_readback_with_command_list(resource->resource, 0, rb,
test_context->queue, test_context->list);
reset_command_list(test_context->list, test_context->allocator);
transition_resource_state(test_context->list, resource->resource,
- D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ D3D12_RESOURCE_STATE_COPY_SOURCE, state);
return &rb->rb;
}
diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c
index adb69a7ce..190441263 100644
--- a/tests/shader_runner_vulkan.c
+++ b/tests/shader_runner_vulkan.c
@@ -943,8 +943,12 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad
struct vulkan_resource *resource = vulkan_resource(res);
VkDevice device = runner->device;
VkBufferImageCopy region = {0};
+ VkImageLayout layout;
- assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET);
+ if (resource->r.type == RESOURCE_TYPE_RENDER_TARGET)
+ layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ else
+ layout = VK_IMAGE_LAYOUT_GENERAL;
rb->rb.width = resource->r.width;
rb->rb.height = resource->r.height;
@@ -957,8 +961,7 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad
begin_command_buffer(runner);
- transition_image_layout(runner, resource->image,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+ transition_image_layout(runner, resource->image, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1;
@@ -969,8 +972,7 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad
VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
- transition_image_layout(runner, resource->image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout);
end_command_buffer(runner);
diff --git a/tests/uav.shader_test b/tests/uav.shader_test
new file mode 100644
index 000000000..09ca05ece
--- /dev/null
+++ b/tests/uav.shader_test
@@ -0,0 +1,56 @@
+[require]
+shader model >= 5.0
+
+[pixel shader fail]
+RWTexture2D<float4> u;
+
+float4 main() : sv_target
+{
+ /* All four components must be written in a single statement. */
+ u[uint2(0, 0)].xy = float4(1, 2);
+ u[uint2(0, 0)].zw = float4(3, 4);
+ return 0;
+}
+
+[pixel shader fail]
+Texture2D<float4> u;
+
+float4 main() : sv_target
+{
+ /* SRVs are not writable. */
+ u[uint2(0, 0)].xyzw = float4(1, 2, 3, 4);
+ return 0;
+}
+
+[uav 1]
+format r32 float
+size (2, 2)
+
+0.1 0.2
+0.3 0.4
+
+[uav 2]
+size (1, 1)
+
+0.5 0.6 0.7 0.8
+
+[pixel shader]
+RWTexture2D<float> u;
+RWTexture2D<float4> v;
+
+float4 main() : sv_target
+{
+ u[uint2(0, 0)] = 0.5;
+ u[uint2(0, 1)].x = 0.6;
+ u[uint2(1, 1)] = 0.7;
+ v[uint2(0, 0)].yxwz = float4(1, 2, 3, 4);
+ return 0;
+}
+
+[test]
+todo draw quad
+probe uav 1 (0, 0) r (0.5)
+probe uav 1 (0, 1) r (0.6)
+probe uav 1 (1, 0) r (0.2)
+probe uav 1 (1, 1) r (0.7)
+probe uav 2 (0, 0) rgba (2.0, 1.0, 4.0, 3.0)
--
2.36.1
June 8, 2022
[PATCH vkd3d v6 3/9] tests/shader_runner: Make the render target into a resource.
by Zebediah Figura
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
tests/shader_runner.c | 57 ++++++++++++++-
tests/shader_runner.h | 6 +-
tests/shader_runner_d3d11.c | 70 +++++++++---------
tests/shader_runner_d3d12.c | 86 ++++++++++++++++------
tests/shader_runner_d3d9.c | 69 +++++++++---------
tests/shader_runner_vulkan.c | 133 ++++++++++++++++++++---------------
6 files changed, 270 insertions(+), 151 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c
index 83f804ad3..f367027f7 100644
--- a/tests/shader_runner.c
+++ b/tests/shader_runner.c
@@ -317,7 +317,27 @@ void init_resource(struct resource *resource, const struct resource_params *para
{
resource->type = params->type;
resource->slot = params->slot;
+ resource->format = params->format;
resource->size = params->data_size;
+ resource->texel_size = params->texel_size;
+ resource->width = params->width;
+ resource->height = params->height;
+}
+
+static struct resource *get_resource(struct shader_runner *runner, enum resource_type type, unsigned int slot)
+{
+ struct resource *resource;
+ size_t i;
+
+ for (i = 0; i < runner->resource_count; ++i)
+ {
+ resource = runner->resources[i];
+
+ if (resource->type == type && resource->slot == slot)
+ return resource;
+ }
+
+ return NULL;
}
static void set_resource(struct shader_runner *runner, struct resource *resource)
@@ -373,6 +393,20 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
"{\n"
"}";
+ if (!get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0))
+ {
+ memset(¶ms, 0, sizeof(params));
+ params.slot = 0;
+ params.type = RESOURCE_TYPE_RENDER_TARGET;
+ params.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ params.data_type = TEXTURE_DATA_FLOAT;
+ params.texel_size = 16;
+ params.width = RENDER_TARGET_WIDTH;
+ params.height = RENDER_TARGET_HEIGHT;
+
+ set_resource(runner, runner->ops->create_resource(runner, ¶ms));
+ }
+
vkd3d_array_reserve((void **)&runner->input_elements, &runner->input_element_capacity,
1, sizeof(*runner->input_elements));
element = &runner->input_elements[0];
@@ -399,9 +433,24 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
else if (match_string(line, "draw", &line))
{
D3D_PRIMITIVE_TOPOLOGY topology;
+ struct resource_params params;
unsigned int vertex_count;
char *rest;
+ if (!get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0))
+ {
+ memset(¶ms, 0, sizeof(params));
+ params.slot = 0;
+ params.type = RESOURCE_TYPE_RENDER_TARGET;
+ params.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ params.data_type = TEXTURE_DATA_FLOAT;
+ params.texel_size = 16;
+ params.width = RENDER_TARGET_WIDTH;
+ params.height = RENDER_TARGET_HEIGHT;
+
+ set_resource(runner, runner->ops->create_resource(runner, ¶ms));
+ }
+
if (match_string(line, "triangle list", &line))
topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
else if (match_string(line, "triangle strip", &line))
@@ -419,15 +468,19 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
{
unsigned int left, top, right, bottom, ulps;
struct resource_readback *rb;
+ struct resource *resource;
int ret, len;
RECT rect;
if (runner->last_render_failed)
return;
+ resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0);
+ rb = runner->ops->get_resource_readback(runner, resource);
+
if (match_string(line, "all", &line))
{
- set_rect(&rect, 0, 0, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT);
+ set_rect(&rect, 0, 0, resource->width, resource->height);
}
else if (sscanf(line, "( %d , %d , %d , %d )%n", &left, &top, &right, &bottom, &len) == 4)
{
@@ -444,8 +497,6 @@ static void parse_test_directive(struct shader_runner *runner, const char *line)
fatal_error("Malformed probe arguments '%s'.\n", line);
}
- rb = runner->ops->get_rt_readback(runner);
-
if (match_string(line, "rgba", &line))
{
struct vec4 v;
diff --git a/tests/shader_runner.h b/tests/shader_runner.h
index 60f894583..19a48ee85 100644
--- a/tests/shader_runner.h
+++ b/tests/shader_runner.h
@@ -53,6 +53,7 @@ struct sampler
enum resource_type
{
+ RESOURCE_TYPE_RENDER_TARGET,
RESOURCE_TYPE_TEXTURE,
RESOURCE_TYPE_UAV,
RESOURCE_TYPE_VERTEX_BUFFER,
@@ -76,7 +77,10 @@ struct resource
unsigned int slot;
enum resource_type type;
+ DXGI_FORMAT format;
unsigned int size;
+ unsigned int texel_size;
+ unsigned int width, height;
};
struct input_element
@@ -124,7 +128,7 @@ struct shader_runner_ops
struct resource *(*create_resource)(struct shader_runner *runner, const struct resource_params *params);
void (*destroy_resource)(struct shader_runner *runner, struct resource *resource);
bool (*draw)(struct shader_runner *runner, D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count);
- struct resource_readback *(*get_rt_readback)(struct shader_runner *runner);
+ struct resource_readback *(*get_resource_readback)(struct shader_runner *runner, struct resource *resource);
void (*release_readback)(struct shader_runner *runner, struct resource_readback *rb);
};
diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c
index b80a8b65f..8999622d3 100644
--- a/tests/shader_runner_d3d11.c
+++ b/tests/shader_runner_d3d11.c
@@ -43,6 +43,8 @@ struct d3d11_resource
struct resource r;
ID3D11Resource *resource;
+ ID3D11Texture2D *texture;
+ ID3D11RenderTargetView *rtv;
ID3D11ShaderResourceView *srv;
ID3D11UnorderedAccessView *uav;
};
@@ -59,8 +61,6 @@ struct d3d11_shader_runner
ID3D11Device *device;
HWND window;
IDXGISwapChain *swapchain;
- ID3D11Texture2D *rt;
- ID3D11RenderTargetView *rtv;
ID3D11DeviceContext *immediate_context;
};
@@ -276,20 +276,8 @@ static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window)
static BOOL init_test_context(struct d3d11_shader_runner *runner)
{
- const D3D11_TEXTURE2D_DESC texture_desc =
- {
- .Width = RENDER_TARGET_WIDTH,
- .Height = RENDER_TARGET_HEIGHT,
- .MipLevels = 1,
- .ArraySize = 1,
- .Format = DXGI_FORMAT_R32G32B32A32_FLOAT,
- .SampleDesc.Count = 1,
- .Usage = D3D11_USAGE_DEFAULT,
- .BindFlags = D3D11_BIND_RENDER_TARGET,
- };
unsigned int rt_width, rt_height;
D3D11_VIEWPORT vp;
- HRESULT hr;
RECT rect;
memset(runner, 0, sizeof(*runner));
@@ -308,16 +296,8 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner)
0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
runner->swapchain = create_swapchain(runner->device, runner->window);
- hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, &runner->rt);
- ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
-
- hr = ID3D11Device_CreateRenderTargetView(runner->device, (ID3D11Resource *)runner->rt, NULL, &runner->rtv);
- ok(hr == S_OK, "Failed to create rendertarget view, hr %#lx.\n", hr);
-
ID3D11Device_GetImmediateContext(runner->device, &runner->immediate_context);
- ID3D11DeviceContext_OMSetRenderTargets(runner->immediate_context, 1, &runner->rtv, NULL);
-
vp.TopLeftX = 0.0f;
vp.TopLeftY = 0.0f;
vp.Width = rt_width;
@@ -334,8 +314,6 @@ static void destroy_test_context(struct d3d11_shader_runner *runner)
ULONG ref;
ID3D11DeviceContext_Release(runner->immediate_context);
- ID3D11RenderTargetView_Release(runner->rtv);
- ID3D11Texture2D_Release(runner->rt);
IDXGISwapChain_Release(runner->swapchain);
DestroyWindow(runner->window);
@@ -379,6 +357,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
switch (params->type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_TEXTURE:
case RESOURCE_TYPE_UAV:
{
@@ -393,17 +372,29 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
desc.Usage = D3D11_USAGE_DEFAULT;
if (params->type == RESOURCE_TYPE_UAV)
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
+ else if (params->type == RESOURCE_TYPE_RENDER_TARGET)
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
else
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- resource_data.pSysMem = params->data;
- resource_data.SysMemPitch = params->width * params->texel_size;
- resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch;
-
- hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, (ID3D11Texture2D **)&resource->resource);
+ if (params->data)
+ {
+ resource_data.pSysMem = params->data;
+ resource_data.SysMemPitch = params->width * params->texel_size;
+ resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch;
+ hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, &resource->texture);
+ }
+ else
+ {
+ hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &resource->texture);
+ }
ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
+
+ resource->resource = (ID3D11Resource *)resource->texture;
if (params->type == RESOURCE_TYPE_UAV)
hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, NULL, &resource->uav);
+ else if (params->type == RESOURCE_TYPE_RENDER_TARGET)
+ hr = ID3D11Device_CreateRenderTargetView(device, resource->resource, NULL, &resource->rtv);
else
hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv);
ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
@@ -424,6 +415,8 @@ static void d3d11_runner_destroy_resource(struct shader_runner *r, struct resour
struct d3d11_resource *resource = d3d11_resource(res);
ID3D11Resource_Release(resource->resource);
+ if (resource->rtv)
+ ID3D11RenderTargetView_Release(resource->rtv);
if (resource->srv)
ID3D11ShaderResourceView_Release(resource->srv);
if (resource->uav)
@@ -435,11 +428,13 @@ static bool d3d11_runner_draw(struct shader_runner *r,
D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count)
{
ID3D11UnorderedAccessView *uavs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
+ ID3D11RenderTargetView *rtvs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
ID3D11DeviceContext *context = runner->immediate_context;
unsigned int min_uav_slot = ARRAY_SIZE(uavs);
ID3D11Device *device = runner->device;
ID3D10Blob *vs_code, *ps_code;
+ unsigned int rtv_count = 0;
ID3D11Buffer *cb = NULL;
ID3D11VertexShader *vs;
ID3D11PixelShader *ps;
@@ -478,6 +473,11 @@ static bool d3d11_runner_draw(struct shader_runner *r,
switch (resource->r.type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
+ rtvs[resource->r.slot] = resource->rtv;
+ rtv_count = max(rtv_count, resource->r.slot + 1);
+ break;
+
case RESOURCE_TYPE_TEXTURE:
ID3D11DeviceContext_PSSetShaderResources(context, resource->r.slot, 1, &resource->srv);
break;
@@ -494,8 +494,7 @@ static bool d3d11_runner_draw(struct shader_runner *r,
}
}
- ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context,
- D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, NULL, NULL,
+ ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, rtv_count, rtvs, NULL,
min_uav_slot, ARRAY_SIZE(uavs) - min_uav_slot, &uavs[min_uav_slot], NULL);
for (i = 0; i < runner->r.sampler_count; ++i)
@@ -565,15 +564,16 @@ struct d3d11_resource_readback
ID3D11Resource *resource;
};
-static struct resource_readback *d3d11_runner_get_rt_readback(struct shader_runner *r)
+static struct resource_readback *d3d11_runner_get_resource_readback(struct shader_runner *r, struct resource *res)
{
struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
struct d3d11_resource_readback *rb = malloc(sizeof(*rb));
+ struct d3d11_resource *resource = d3d11_resource(res);
D3D11_TEXTURE2D_DESC texture_desc;
D3D11_MAPPED_SUBRESOURCE map_desc;
HRESULT hr;
- ID3D11Texture2D_GetDesc(runner->rt, &texture_desc);
+ ID3D11Texture2D_GetDesc(resource->texture, &texture_desc);
texture_desc.Usage = D3D11_USAGE_STAGING;
texture_desc.BindFlags = 0;
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
@@ -581,7 +581,7 @@ static struct resource_readback *d3d11_runner_get_rt_readback(struct shader_runn
hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource);
ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
- ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, (ID3D11Resource *)runner->rt);
+ ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, resource->resource);
hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &map_desc);
ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr);
@@ -608,7 +608,7 @@ static const struct shader_runner_ops d3d11_runner_ops =
.create_resource = d3d11_runner_create_resource,
.destroy_resource = d3d11_runner_destroy_resource,
.draw = d3d11_runner_draw,
- .get_rt_readback = d3d11_runner_get_rt_readback,
+ .get_resource_readback = d3d11_runner_get_resource_readback,
.release_readback = d3d11_runner_release_readback,
};
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index ec08fea54..79d5b8ebb 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -44,7 +44,7 @@ struct d3d12_shader_runner
struct test_context test_context;
- ID3D12DescriptorHeap *heap;
+ ID3D12DescriptorHeap *heap, *rtv_heap;
};
static struct d3d12_shader_runner *d3d12_shader_runner(struct shader_runner *r)
@@ -94,6 +94,20 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co
switch (params->type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
+ if (!runner->rtv_heap)
+ runner->rtv_heap = create_cpu_descriptor_heap(device,
+ D3D12_DESCRIPTOR_HEAP_TYPE_RTV, MAX_RESOURCE_DESCRIPTORS);
+
+ if (params->slot >= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT)
+ fatal_error("RTV slot %u is too high.\n", params->slot);
+
+ resource->resource = create_default_texture(device, params->width, params->height,
+ params->format, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ ID3D12Device_CreateRenderTargetView(device, resource->resource,
+ NULL, get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.slot));
+ break;
+
case RESOURCE_TYPE_TEXTURE:
if (!runner->heap)
runner->heap = create_gpu_descriptor_heap(device,
@@ -150,18 +164,19 @@ static bool d3d12_runner_draw(struct shader_runner *r,
struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
struct test_context *test_context = &runner->test_context;
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
ID3D12GraphicsCommandList *command_list = test_context->list;
D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = {0};
D3D12_ROOT_PARAMETER root_params[3], *root_param;
ID3D12CommandQueue *queue = test_context->queue;
D3D12_INPUT_ELEMENT_DESC *input_element_descs;
D3D12_STATIC_SAMPLER_DESC static_samplers[1];
ID3D12Device *device = test_context->device;
- D3D12_INPUT_LAYOUT_DESC input_layout;
static const float clear_color[4];
+ unsigned int uniform_index = 0;
ID3D10Blob *vs_code, *ps_code;
- D3D12_SHADER_BYTECODE vs, ps;
- unsigned int uniform_index;
+ unsigned int rtv_count = 0;
ID3D12PipelineState *pso;
HRESULT hr;
size_t i;
@@ -185,6 +200,16 @@ static bool d3d12_runner_draw(struct shader_runner *r,
root_signature_desc.pStaticSamplers = static_samplers;
root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+ pso_desc.VS.pShaderBytecode = ID3D10Blob_GetBufferPointer(vs_code);
+ pso_desc.VS.BytecodeLength = ID3D10Blob_GetBufferSize(vs_code);
+ pso_desc.PS.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code);
+ pso_desc.PS.BytecodeLength = ID3D10Blob_GetBufferSize(ps_code);
+ pso_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
+ pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
+ pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ pso_desc.SampleDesc.Count = 1;
+ pso_desc.SampleMask = ~(UINT)0;
+
if (runner->r.uniform_count)
{
uniform_index = root_signature_desc.NumParameters++;
@@ -224,6 +249,12 @@ static bool d3d12_runner_draw(struct shader_runner *r,
range->OffsetInDescriptorsFromTableStart = 0;
break;
+ case RESOURCE_TYPE_RENDER_TARGET:
+ pso_desc.RTVFormats[resource->r.slot] = resource->r.format;
+ pso_desc.NumRenderTargets = max(pso_desc.NumRenderTargets, resource->r.slot + 1);
+ pso_desc.BlendState.RenderTarget[resource->r.slot].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
break;
}
@@ -251,6 +282,8 @@ static bool d3d12_runner_draw(struct shader_runner *r,
hr = create_root_signature(device, &root_signature_desc, &test_context->root_signature);
ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
+ pso_desc.pRootSignature = test_context->root_signature;
+
input_element_descs = calloc(runner->r.input_element_count, sizeof(*input_element_descs));
for (i = 0; i < runner->r.input_element_count; ++i)
{
@@ -265,15 +298,12 @@ static bool d3d12_runner_draw(struct shader_runner *r,
desc->InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
}
- input_layout.pInputElementDescs = input_element_descs;
- input_layout.NumElements = runner->r.input_element_count;
+ pso_desc.InputLayout.pInputElementDescs = input_element_descs;
+ pso_desc.InputLayout.NumElements = runner->r.input_element_count;
- vs.pShaderBytecode = ID3D10Blob_GetBufferPointer(vs_code);
- vs.BytecodeLength = ID3D10Blob_GetBufferSize(vs_code);
- ps.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code);
- ps.BytecodeLength = ID3D10Blob_GetBufferSize(ps_code);
- pso = create_pipeline_state(device, test_context->root_signature,
- test_context->render_target_desc.Format, &vs, &ps, &input_layout);
+ hr = ID3D12Device_CreateGraphicsPipelineState(device, &pso_desc,
+ &IID_ID3D12PipelineState, (void **)&pso);
+ ok(hr == S_OK, "Failed to create state, hr %#x.\n", hr);
ID3D10Blob_Release(vs_code);
ID3D10Blob_Release(ps_code);
free(input_element_descs);
@@ -292,6 +322,13 @@ static bool d3d12_runner_draw(struct shader_runner *r,
switch (resource->r.type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
+ rtvs[resource->r.slot] = get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.slot);
+ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list,
+ rtvs[resource->r.slot], clear_color, 0, NULL);
+ rtv_count = max(rtv_count, resource->r.slot + 1);
+ break;
+
case RESOURCE_TYPE_TEXTURE:
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index,
get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot));
@@ -312,11 +349,11 @@ static bool d3d12_runner_draw(struct shader_runner *r,
}
}
- ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &test_context->rtv, false, NULL);
+ ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, rtv_count, rtvs, false, NULL);
+
ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &test_context->scissor_rect);
ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &test_context->viewport);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, primitive_topology);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, test_context->rtv, clear_color, 0, NULL);
ID3D12GraphicsCommandList_SetPipelineState(command_list, pso);
ID3D12GraphicsCommandList_DrawInstanced(command_list, vertex_count, 1, 0, 0);
@@ -330,16 +367,22 @@ static bool d3d12_runner_draw(struct shader_runner *r,
return true;
}
-static struct resource_readback *d3d12_runner_get_rt_readback(struct shader_runner *r)
+static struct resource_readback *d3d12_runner_get_resource_readback(struct shader_runner *r, struct resource *res)
{
struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
struct test_context *test_context = &runner->test_context;
struct d3d12_resource_readback *rb = malloc(sizeof(*rb));
+ struct d3d12_resource *resource = d3d12_resource(res);
- transition_resource_state(test_context->list, test_context->render_target,
+ assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET);
+
+ transition_resource_state(test_context->list, resource->resource,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
- get_texture_readback_with_command_list(test_context->render_target, 0, rb,
+ get_texture_readback_with_command_list(resource->resource, 0, rb,
test_context->queue, test_context->list);
+ reset_command_list(test_context->list, test_context->allocator);
+ transition_resource_state(test_context->list, resource->resource,
+ D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
return &rb->rb;
}
@@ -347,13 +390,8 @@ static struct resource_readback *d3d12_runner_get_rt_readback(struct shader_runn
static void d3d12_runner_release_readback(struct shader_runner *r, struct resource_readback *rb)
{
struct d3d12_resource_readback *d3d12_rb = CONTAINING_RECORD(rb, struct d3d12_resource_readback, rb);
- struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
- struct test_context *test_context = &runner->test_context;
release_resource_readback(d3d12_rb);
- reset_command_list(test_context->list, test_context->allocator);
- transition_resource_state(test_context->list, test_context->render_target,
- D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET);
free(d3d12_rb);
}
@@ -362,7 +400,7 @@ static const struct shader_runner_ops d3d12_runner_ops =
.create_resource = d3d12_runner_create_resource,
.destroy_resource = d3d12_runner_destroy_resource,
.draw = d3d12_runner_draw,
- .get_rt_readback = d3d12_runner_get_rt_readback,
+ .get_resource_readback = d3d12_runner_get_resource_readback,
.release_readback = d3d12_runner_release_readback,
};
@@ -386,5 +424,7 @@ void run_shader_tests_d3d12(int argc, char **argv)
if (runner.heap)
ID3D12DescriptorHeap_Release(runner.heap);
+ if (runner.rtv_heap)
+ ID3D12DescriptorHeap_Release(runner.rtv_heap);
destroy_test_context(&runner.test_context);
}
diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c
index 417d68750..583b7ca73 100644
--- a/tests/shader_runner_d3d9.c
+++ b/tests/shader_runner_d3d9.c
@@ -29,6 +29,7 @@ struct d3d9_resource
{
struct resource r;
+ IDirect3DSurface9 *surface;
IDirect3DTexture9 *texture;
IDirect3DVertexBuffer9 *vb;
};
@@ -43,7 +44,6 @@ struct d3d9_shader_runner
struct shader_runner r;
IDirect3DDevice9 *device;
- IDirect3DSurface9 *rt;
HWND window;
};
@@ -151,18 +151,6 @@ static bool init_test_context(struct d3d9_shader_runner *runner)
return false;
}
- if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(runner->device, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT,
- D3DFMT_A32B32G32R32F, D3DMULTISAMPLE_NONE, 0, FALSE, &runner->rt, NULL)))
- {
- skip("Failed to create an A32B32G32R32F surface, hr %#lx.\n", hr);
- IDirect3DDevice9_Release(runner->device);
- DestroyWindow(runner->window);
- return false;
- }
- ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
- hr = IDirect3DDevice9_SetRenderTarget(runner->device, 0, runner->rt);
- ok(hr == D3D_OK, "Failed to set render target, hr %#lx.\n", hr);
-
return true;
}
@@ -170,7 +158,6 @@ static void destroy_test_context(struct d3d9_shader_runner *runner)
{
ULONG ref;
- IDirect3DSurface9_Release(runner->rt);
ref = IDirect3DDevice9_Release(runner->device);
ok(!ref, "Device has %lu references left.\n", ref);
DestroyWindow(runner->window);
@@ -224,24 +211,30 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con
resource = calloc(1, sizeof(*resource));
init_resource(&resource->r, params);
+ switch (params->format)
+ {
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ format = D3DFMT_A32B32G32R32F;
+ break;
+
+ case DXGI_FORMAT_R32_FLOAT:
+ format = D3DFMT_R32F;
+ break;
+
+ default:
+ format = D3DFMT_UNKNOWN;
+ break;
+ }
+
switch (params->type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
+ hr = IDirect3DDevice9_CreateRenderTarget(device, params->width, params->height,
+ format, D3DMULTISAMPLE_NONE, 0, FALSE, &resource->surface, NULL);
+ ok(hr == D3D_OK, "Failed to create render target, hr %#lx.\n", hr);
+ break;
+
case RESOURCE_TYPE_TEXTURE:
- switch (params->format)
- {
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- format = D3DFMT_A32B32G32R32F;
- break;
-
- case DXGI_FORMAT_R32_FLOAT:
- format = D3DFMT_R32F;
- break;
-
- default:
- format = D3DFMT_UNKNOWN;
- break;
- }
-
hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height,
1, D3DUSAGE_DYNAMIC, format, D3DPOOL_DEFAULT, &resource->texture, NULL);
ok(hr == D3D_OK, "Failed to create texture, hr %#lx.\n", hr);
@@ -279,6 +272,8 @@ static void d3d9_runner_destroy_resource(struct shader_runner *r, struct resourc
{
struct d3d9_resource *resource = d3d9_resource(res);
+ if (resource->surface)
+ IDirect3DSurface9_Release(resource->surface);
if (resource->texture)
IDirect3DTexture9_Release(resource->texture);
if (resource->vb)
@@ -363,6 +358,11 @@ static bool d3d9_runner_draw(struct shader_runner *r,
switch (resource->r.type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
+ hr = IDirect3DDevice9_SetRenderTarget(device, resource->r.slot, resource->surface);
+ ok(hr == D3D_OK, "Failed to set render target, hr %#lx.\n", hr);
+ break;
+
case RESOURCE_TYPE_TEXTURE:
hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture);
ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr);
@@ -461,21 +461,24 @@ struct d3d9_resource_readback
IDirect3DSurface9 *surface;
};
-static struct resource_readback *d3d9_runner_get_rt_readback(struct shader_runner *r)
+static struct resource_readback *d3d9_runner_get_resource_readback(struct shader_runner *r, struct resource *res)
{
struct d3d9_shader_runner *runner = d3d9_shader_runner(r);
struct d3d9_resource_readback *rb = malloc(sizeof(*rb));
+ struct d3d9_resource *resource = d3d9_resource(res);
D3DLOCKED_RECT map_desc;
D3DSURFACE_DESC desc;
HRESULT hr;
- hr = IDirect3DSurface9_GetDesc(runner->rt, &desc);
+ assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET);
+
+ hr = IDirect3DSurface9_GetDesc(resource->surface, &desc);
ok(hr == D3D_OK, "Failed to get surface desc, hr %#lx.\n", hr);
hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(runner->device, desc.Width,
desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &rb->surface, NULL);
ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr);
- hr = IDirect3DDevice9Ex_GetRenderTargetData(runner->device, runner->rt, rb->surface);
+ hr = IDirect3DDevice9Ex_GetRenderTargetData(runner->device, resource->surface, rb->surface);
ok(hr == D3D_OK, "Failed to get render target data, hr %#lx.\n", hr);
hr = IDirect3DSurface9_LockRect(rb->surface, &map_desc, NULL, D3DLOCK_READONLY);
@@ -504,7 +507,7 @@ static const struct shader_runner_ops d3d9_runner_ops =
.create_resource = d3d9_runner_create_resource,
.destroy_resource = d3d9_runner_destroy_resource,
.draw = d3d9_runner_draw,
- .get_rt_readback = d3d9_runner_get_rt_readback,
+ .get_resource_readback = d3d9_runner_get_resource_readback,
.release_readback = d3d9_runner_release_readback,
};
diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c
index d62792d65..adb69a7ce 100644
--- a/tests/shader_runner_vulkan.c
+++ b/tests/shader_runner_vulkan.c
@@ -60,10 +60,6 @@ struct vulkan_shader_runner
VkCommandBuffer cmd_buffer;
VkDescriptorPool descriptor_pool;
- VkImage render_target;
- VkDeviceMemory rt_memory;
- VkImageView rtv;
-
struct vulkan_sampler
{
VkSampler vk_sampler;
@@ -247,6 +243,19 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
switch (params->type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
+ format = vkd3d_get_vk_format(params->format);
+
+ resource->image = create_2d_image(runner, params->width, params->height,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory);
+ resource->view = create_2d_image_view(runner, resource->image, format);
+
+ begin_command_buffer(runner);
+ transition_image_layout(runner, resource->image,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ end_command_buffer(runner);
+ break;
+
case RESOURCE_TYPE_TEXTURE:
case RESOURCE_TYPE_UAV:
{
@@ -385,6 +394,7 @@ static bool compile_shader(const struct vulkan_shader_runner *runner, const char
switch (resource->r.type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_VERTEX_BUFFER:
break;
@@ -514,7 +524,7 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR
VkPipelineViewportStateCreateInfo vp_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
static const VkRect2D rt_rect = {.extent.width = RENDER_TARGET_WIDTH, .extent.height = RENDER_TARGET_HEIGHT};
VkGraphicsPipelineCreateInfo pipeline_desc = {.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
- VkPipelineColorBlendAttachmentState attachment_desc = {0};
+ VkPipelineColorBlendAttachmentState attachment_desc[MAX_RESOURCES] = {0};
VkVertexInputAttributeDescription input_attributes[32];
VkVertexInputBindingDescription input_bindings[32];
struct vkd3d_shader_signature vs_input_signature;
@@ -560,6 +570,9 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR
input_desc.pVertexAttributeDescriptions = input_attributes;
input_desc.pVertexBindingDescriptions = input_bindings;
+ blend_desc.attachmentCount = 0;
+ blend_desc.pAttachments = attachment_desc;
+
for (i = 0; i < runner->r.resource_count; ++i)
{
const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
@@ -570,6 +583,12 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR
case RESOURCE_TYPE_UAV:
break;
+ case RESOURCE_TYPE_RENDER_TARGET:
+ attachment_desc[blend_desc.attachmentCount++].colorWriteMask =
+ VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
+ | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
{
VkVertexInputBindingDescription *binding = &input_bindings[input_desc.vertexBindingDescriptionCount++];
@@ -603,12 +622,6 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR
ms_desc.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
- blend_desc.attachmentCount = 1;
- blend_desc.pAttachments = &attachment_desc;
-
- attachment_desc.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
- | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
-
pipeline_desc.stageCount = ARRAY_SIZE(stage_desc);
pipeline_desc.pStages = stage_desc;
pipeline_desc.pVertexInputState = &input_desc;
@@ -669,6 +682,7 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r
switch (resource->r.type)
{
+ case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_VERTEX_BUFFER:
break;
@@ -768,6 +782,9 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo
if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS)
VK_CALL(vkCmdBindVertexBuffers(cmd_buffer, resource->r.slot, 1, &resource->buffer, &zero_offset));
break;
+
+ case RESOURCE_TYPE_RENDER_TARGET:
+ break;
}
}
@@ -785,36 +802,53 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn
{
VkRenderPassCreateInfo render_pass_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
VkFramebufferCreateInfo fb_desc = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
- VkAttachmentDescription attachment_desc = {0};
+ VkAttachmentDescription attachment_descs[MAX_RESOURCES] = {0};
+ VkAttachmentReference color_refs[MAX_RESOURCES] = {0};
VkSubpassDescription subpass_desc = {0};
- VkAttachmentReference color_ref = {0};
+ VkImageView rtvs[MAX_RESOURCES];
+ unsigned int rt_count = 0;
+ unsigned int i;
- attachment_desc.format = VK_FORMAT_R32G32B32A32_SFLOAT;
- attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT;
- attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachment_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ for (i = 0; i < runner->r.resource_count; ++i)
+ {
+ const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
+ VkAttachmentDescription *attachment_desc = &attachment_descs[rt_count];
+ VkAttachmentReference *color_ref = &color_refs[rt_count];
- color_ref.attachment = 0;
- color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ if (resource->r.type != RESOURCE_TYPE_RENDER_TARGET)
+ continue;
+
+ attachment_desc->format = vkd3d_get_vk_format(resource->r.format);
+ attachment_desc->samples = VK_SAMPLE_COUNT_1_BIT;
+ attachment_desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ attachment_desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment_desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachment_desc->initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachment_desc->finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ color_ref->attachment = rt_count;
+ color_ref->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ rtvs[rt_count] = resource->view;
+
+ ++rt_count;
+ }
subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass_desc.colorAttachmentCount = 1;
- subpass_desc.pColorAttachments = &color_ref;
+ subpass_desc.colorAttachmentCount = rt_count;
+ subpass_desc.pColorAttachments = color_refs;
- render_pass_desc.attachmentCount = 1;
- render_pass_desc.pAttachments = &attachment_desc;
+ render_pass_desc.attachmentCount = rt_count;
+ render_pass_desc.pAttachments = attachment_descs;
render_pass_desc.subpassCount = 1;
render_pass_desc.pSubpasses = &subpass_desc;
VK_CALL(vkCreateRenderPass(runner->device, &render_pass_desc, NULL, render_pass));
fb_desc.renderPass = *render_pass;
- fb_desc.attachmentCount = 1;
- fb_desc.pAttachments = &runner->rtv;
+ fb_desc.attachmentCount = rt_count;
+ fb_desc.pAttachments = rtvs;
fb_desc.width = RENDER_TARGET_WIDTH;
fb_desc.height = RENDER_TARGET_HEIGHT;
fb_desc.layers = 1;
@@ -902,37 +936,40 @@ struct vulkan_resource_readback
VkBuffer buffer;
};
-static struct resource_readback *vulkan_runner_get_rt_readback(struct shader_runner *r)
+static struct resource_readback *vulkan_runner_get_resource_readback(struct shader_runner *r, struct resource *res)
{
struct vulkan_shader_runner *runner = vulkan_shader_runner(r);
struct vulkan_resource_readback *rb = malloc(sizeof(*rb));
+ struct vulkan_resource *resource = vulkan_resource(res);
VkDevice device = runner->device;
VkBufferImageCopy region = {0};
- rb->rb.width = RENDER_TARGET_WIDTH;
- rb->rb.height = RENDER_TARGET_HEIGHT;
+ assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET);
+
+ rb->rb.width = resource->r.width;
+ rb->rb.height = resource->r.height;
rb->rb.depth = 1;
- rb->rb.row_pitch = rb->rb.width * sizeof(struct vec4);
+ rb->rb.row_pitch = rb->rb.width * resource->r.texel_size;
- rb->buffer = create_buffer(runner, rb->rb.row_pitch * RENDER_TARGET_HEIGHT,
+ rb->buffer = create_buffer(runner, rb->rb.row_pitch * rb->rb.height,
VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &rb->memory);
begin_command_buffer(runner);
- transition_image_layout(runner, runner->render_target,
+ transition_image_layout(runner, resource->image,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1;
- region.imageExtent.width = RENDER_TARGET_WIDTH;
- region.imageExtent.height = RENDER_TARGET_HEIGHT;
+ region.imageExtent.width = resource->r.width;
+ region.imageExtent.height = resource->r.height;
region.imageExtent.depth = 1;
- VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, runner->render_target,
+ VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion));
- transition_image_layout(runner, runner->render_target,
+ transition_image_layout(runner, resource->image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
end_command_buffer(runner);
@@ -959,7 +996,7 @@ static const struct shader_runner_ops vulkan_runner_ops =
.create_resource = vulkan_runner_create_resource,
.destroy_resource = vulkan_runner_destroy_resource,
.draw = vulkan_runner_draw,
- .get_rt_readback = vulkan_runner_get_rt_readback,
+ .get_resource_readback = vulkan_runner_get_resource_readback,
.release_readback = vulkan_runner_release_readback,
};
@@ -1141,11 +1178,6 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
VK_CALL(vkAllocateCommandBuffers(device, &cmd_buffer_desc, &runner->cmd_buffer));
- runner->render_target = create_2d_image(runner, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT,
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
- VK_FORMAT_R32G32B32A32_SFLOAT, &runner->rt_memory);
- runner->rtv = create_2d_image_view(runner, runner->render_target, VK_FORMAT_R32G32B32A32_SFLOAT);
-
descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor_pool_sizes[0].descriptorCount = MAX_RESOURCES;
descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
@@ -1159,13 +1191,6 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
VK_CALL(vkCreateDescriptorPool(device, &descriptor_pool_desc, NULL, &runner->descriptor_pool));
- begin_command_buffer(runner);
-
- transition_image_layout(runner, runner->render_target,
- VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- end_command_buffer(runner);
-
return true;
out_destroy_instance:
@@ -1177,10 +1202,6 @@ static void cleanup_vulkan_runner(struct vulkan_shader_runner *runner)
{
VkDevice device = runner->device;
- VK_CALL(vkFreeMemory(device, runner->rt_memory, NULL));
- VK_CALL(vkDestroyImageView(device, runner->rtv, NULL));
- VK_CALL(vkDestroyImage(device, runner->render_target, NULL));
-
VK_CALL(vkDestroyDescriptorPool(device, runner->descriptor_pool, NULL));
VK_CALL(vkFreeCommandBuffers(device, runner->command_pool, 1, &runner->cmd_buffer));
VK_CALL(vkDestroyCommandPool(device, runner->command_pool, NULL));
--
2.36.1
June 8, 2022
[PATCH vkd3d v6 2/9] tests/shader_runner: Create the render pass and framebuffer in vulkan_runner_draw().
by Zebediah Figura
Prepare to allow for dynamically changing the bound attachments in consecutive
draw calls.
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
tests/shader_runner_vulkan.c | 99 +++++++++++++++++++-----------------
1 file changed, 53 insertions(+), 46 deletions(-)
diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c
index f5a0e7ec3..d62792d65 100644
--- a/tests/shader_runner_vulkan.c
+++ b/tests/shader_runner_vulkan.c
@@ -58,13 +58,11 @@ struct vulkan_shader_runner
VkQueue queue;
VkCommandPool command_pool;
VkCommandBuffer cmd_buffer;
- VkRenderPass render_pass;
VkDescriptorPool descriptor_pool;
VkImage render_target;
VkDeviceMemory rt_memory;
VkImageView rtv;
- VkFramebuffer fb;
struct vulkan_sampler
{
@@ -504,7 +502,7 @@ static VkPipelineLayout create_pipeline_layout(const struct vulkan_shader_runner
return pipeline_layout;
}
-static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner,
+static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkRenderPass render_pass,
VkPipelineLayout pipeline_layout, D3D_PRIMITIVE_TOPOLOGY primitive_topology)
{
VkPipelineInputAssemblyStateCreateInfo ia_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
@@ -620,7 +618,7 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner,
pipeline_desc.pMultisampleState = &ms_desc;
pipeline_desc.pColorBlendState = &blend_desc;
pipeline_desc.layout = pipeline_layout;
- pipeline_desc.renderPass = runner->render_pass;
+ pipeline_desc.renderPass = render_pass;
pipeline_desc.subpass = 0;
VK_CALL(vkCreateGraphicsPipelines(runner->device, VK_NULL_HANDLE, 1, &pipeline_desc, NULL, &pipeline));
@@ -782,6 +780,48 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo
/* The descriptor set will be freed by resetting the descriptor pool. */
}
+static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runner,
+ VkRenderPass *render_pass, VkFramebuffer *fb)
+{
+ VkRenderPassCreateInfo render_pass_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
+ VkFramebufferCreateInfo fb_desc = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
+ VkAttachmentDescription attachment_desc = {0};
+ VkSubpassDescription subpass_desc = {0};
+ VkAttachmentReference color_ref = {0};
+
+ attachment_desc.format = VK_FORMAT_R32G32B32A32_SFLOAT;
+ attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT;
+ attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attachment_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ color_ref.attachment = 0;
+ color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass_desc.colorAttachmentCount = 1;
+ subpass_desc.pColorAttachments = &color_ref;
+
+ render_pass_desc.attachmentCount = 1;
+ render_pass_desc.pAttachments = &attachment_desc;
+ render_pass_desc.subpassCount = 1;
+ render_pass_desc.pSubpasses = &subpass_desc;
+
+ VK_CALL(vkCreateRenderPass(runner->device, &render_pass_desc, NULL, render_pass));
+
+ fb_desc.renderPass = *render_pass;
+ fb_desc.attachmentCount = 1;
+ fb_desc.pAttachments = &runner->rtv;
+ fb_desc.width = RENDER_TARGET_WIDTH;
+ fb_desc.height = RENDER_TARGET_HEIGHT;
+ fb_desc.layers = 1;
+
+ VK_CALL(vkCreateFramebuffer(runner->device, &fb_desc, NULL, fb));
+}
+
static bool vulkan_runner_draw(struct shader_runner *r,
D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count)
{
@@ -794,16 +834,20 @@ static bool vulkan_runner_draw(struct shader_runner *r,
VkDescriptorSetLayout set_layout;
VkPipelineLayout pipeline_layout;
VkDevice device = runner->device;
+ VkRenderPass render_pass;
VkClearRect clear_rect;
VkPipeline pipeline;
+ VkFramebuffer fb;
bool ret = true;
unsigned int i;
+ create_render_pass_and_framebuffer(runner, &render_pass, &fb);
+
/* Create this before compiling shaders, it will assign resource bindings. */
set_layout = create_descriptor_set_layout(runner);
pipeline_layout = create_pipeline_layout(runner, set_layout);
- if (!(pipeline = create_pipeline(runner, pipeline_layout, primitive_topology)))
+ if (!(pipeline = create_pipeline(runner, render_pass, pipeline_layout, primitive_topology)))
{
ret = false;
goto out;
@@ -811,8 +855,8 @@ static bool vulkan_runner_draw(struct shader_runner *r,
begin_command_buffer(runner);
- pass_begin_desc.renderPass = runner->render_pass;
- pass_begin_desc.framebuffer = runner->fb;
+ pass_begin_desc.renderPass = render_pass;
+ pass_begin_desc.framebuffer = fb;
pass_begin_desc.renderArea = rt_rect;
VK_CALL(vkCmdBeginRenderPass(cmd_buffer, &pass_begin_desc, VK_SUBPASS_CONTENTS_INLINE));
@@ -845,6 +889,8 @@ out:
VK_CALL(vkDestroyPipelineLayout(device, pipeline_layout, NULL));
VK_CALL(vkDestroyDescriptorSetLayout(device, set_layout, NULL));
+ VK_CALL(vkDestroyRenderPass(device, render_pass, NULL));
+ VK_CALL(vkDestroyFramebuffer(device, fb, NULL));
return ret;
}
@@ -985,17 +1031,12 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
VkDescriptorPoolCreateInfo descriptor_pool_desc = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
VkCommandBufferAllocateInfo cmd_buffer_desc = {.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
VkCommandPoolCreateInfo command_pool_desc = {.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
- VkRenderPassCreateInfo render_pass_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
VkDeviceQueueCreateInfo queue_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
- VkFramebufferCreateInfo fb_desc = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
VkInstanceCreateInfo instance_desc = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
VkDeviceCreateInfo device_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
VkPhysicalDeviceFeatures ret_features, features;
VkDescriptorPoolSize descriptor_pool_sizes[3];
- VkAttachmentDescription attachment_desc = {0};
static const float queue_priority = 1.0f;
- VkSubpassDescription subpass_desc = {0};
- VkAttachmentReference color_ref = {0};
VkFormatProperties format_props;
uint32_t count, graphics_index;
VkDevice device;
@@ -1100,43 +1141,11 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
VK_CALL(vkAllocateCommandBuffers(device, &cmd_buffer_desc, &runner->cmd_buffer));
- attachment_desc.format = VK_FORMAT_R32G32B32A32_SFLOAT;
- attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT;
- attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachment_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- color_ref.attachment = 0;
- color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass_desc.colorAttachmentCount = 1;
- subpass_desc.pColorAttachments = &color_ref;
-
- render_pass_desc.attachmentCount = 1;
- render_pass_desc.pAttachments = &attachment_desc;
- render_pass_desc.subpassCount = 1;
- render_pass_desc.pSubpasses = &subpass_desc;
-
- VK_CALL(vkCreateRenderPass(device, &render_pass_desc, NULL, &runner->render_pass));
-
runner->render_target = create_2d_image(runner, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_FORMAT_R32G32B32A32_SFLOAT, &runner->rt_memory);
runner->rtv = create_2d_image_view(runner, runner->render_target, VK_FORMAT_R32G32B32A32_SFLOAT);
- fb_desc.renderPass = runner->render_pass;
- fb_desc.attachmentCount = 1;
- fb_desc.pAttachments = &runner->rtv;
- fb_desc.width = RENDER_TARGET_WIDTH;
- fb_desc.height = RENDER_TARGET_HEIGHT;
- fb_desc.layers = 1;
-
- VK_CALL(vkCreateFramebuffer(device, &fb_desc, NULL, &runner->fb));
-
descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor_pool_sizes[0].descriptorCount = MAX_RESOURCES;
descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
@@ -1169,12 +1178,10 @@ static void cleanup_vulkan_runner(struct vulkan_shader_runner *runner)
VkDevice device = runner->device;
VK_CALL(vkFreeMemory(device, runner->rt_memory, NULL));
- VK_CALL(vkDestroyFramebuffer(device, runner->fb, NULL));
VK_CALL(vkDestroyImageView(device, runner->rtv, NULL));
VK_CALL(vkDestroyImage(device, runner->render_target, NULL));
VK_CALL(vkDestroyDescriptorPool(device, runner->descriptor_pool, NULL));
- VK_CALL(vkDestroyRenderPass(device, runner->render_pass, NULL));
VK_CALL(vkFreeCommandBuffers(device, runner->command_pool, 1, &runner->cmd_buffer));
VK_CALL(vkDestroyCommandPool(device, runner->command_pool, NULL));
VK_CALL(vkDestroyDevice(device, NULL));
--
2.36.1
June 8, 2022
[PATCH vkd3d v6 1/9] tests/shader_runner: Allow creating UAV resources.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
v6: avoid magic numbers...
tests/shader_runner.c | 38 +++++++++++++++++++---------
tests/shader_runner.h | 2 ++
tests/shader_runner_d3d11.c | 31 ++++++++++++++++++-----
tests/shader_runner_d3d12.c | 37 +++++++++++++++++++++------
tests/shader_runner_d3d9.c | 12 ++++++---
tests/shader_runner_vulkan.c | 48 ++++++++++++++++++++++++++++--------
6 files changed, 130 insertions(+), 38 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c
index 05e2a8a41..83f804ad3 100644
--- a/tests/shader_runner.c
+++ b/tests/shader_runner.c
@@ -78,14 +78,13 @@ enum parse_state
STATE_PREPROC,
STATE_PREPROC_INVALID,
STATE_REQUIRE,
+ STATE_RESOURCE,
STATE_SAMPLER,
STATE_SHADER_INVALID_PIXEL,
STATE_SHADER_INVALID_PIXEL_TODO,
STATE_SHADER_PIXEL,
STATE_SHADER_VERTEX,
- STATE_TEXTURE,
STATE_TEST,
- STATE_VERTEX_BUFFER,
};
static bool match_string(const char *line, const char *token, const char **const rest)
@@ -314,6 +313,13 @@ static void parse_input_layout_directive(struct shader_runner *runner, const cha
element->index = 0;
}
+void init_resource(struct resource *resource, const struct resource_params *params)
+{
+ resource->type = params->type;
+ resource->slot = params->slot;
+ resource->size = params->data_size;
+}
+
static void set_resource(struct shader_runner *runner, struct resource *resource)
{
size_t i;
@@ -617,8 +623,7 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
goto out;
break;
- case STATE_TEXTURE:
- case STATE_VERTEX_BUFFER:
+ case STATE_RESOURCE:
set_resource(runner, runner->ops->create_resource(runner, ¤t_resource));
free(current_resource.data);
break;
@@ -766,7 +771,7 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
}
else if (sscanf(line, "[texture %u]\n", &index))
{
- state = STATE_TEXTURE;
+ state = STATE_RESOURCE;
memset(¤t_resource, 0, sizeof(current_resource));
@@ -776,9 +781,21 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
current_resource.data_type = TEXTURE_DATA_FLOAT;
current_resource.texel_size = 16;
}
+ else if (sscanf(line, "[uav %u]\n", &index))
+ {
+ state = STATE_RESOURCE;
+
+ memset(¤t_resource, 0, sizeof(current_resource));
+
+ current_resource.slot = index;
+ current_resource.type = RESOURCE_TYPE_UAV;
+ current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ current_resource.data_type = TEXTURE_DATA_FLOAT;
+ current_resource.texel_size = 16;
+ }
else if (sscanf(line, "[vertex buffer %u]\n", &index))
{
- state = STATE_VERTEX_BUFFER;
+ state = STATE_RESOURCE;
memset(¤t_resource, 0, sizeof(current_resource));
@@ -844,13 +861,12 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
parse_require_directive(runner, line);
break;
- case STATE_SAMPLER:
- parse_sampler_directive(current_sampler, line);
+ case STATE_RESOURCE:
+ parse_resource_directive(¤t_resource, line);
break;
- case STATE_TEXTURE:
- case STATE_VERTEX_BUFFER:
- parse_resource_directive(¤t_resource, line);
+ case STATE_SAMPLER:
+ parse_sampler_directive(current_sampler, line);
break;
case STATE_TEST:
diff --git a/tests/shader_runner.h b/tests/shader_runner.h
index 6ed0109e6..60f894583 100644
--- a/tests/shader_runner.h
+++ b/tests/shader_runner.h
@@ -54,6 +54,7 @@ struct sampler
enum resource_type
{
RESOURCE_TYPE_TEXTURE,
+ RESOURCE_TYPE_UAV,
RESOURCE_TYPE_VERTEX_BUFFER,
};
@@ -130,6 +131,7 @@ struct shader_runner_ops
void fatal_error(const char *format, ...) VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2);
unsigned int get_vb_stride(const struct shader_runner *runner, unsigned int slot);
+void init_resource(struct resource *resource, const struct resource_params *params);
void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const struct shader_runner_ops *ops);
diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c
index 6edbdf75e..b80a8b65f 100644
--- a/tests/shader_runner_d3d11.c
+++ b/tests/shader_runner_d3d11.c
@@ -44,6 +44,7 @@ struct d3d11_resource
ID3D11Resource *resource;
ID3D11ShaderResourceView *srv;
+ ID3D11UnorderedAccessView *uav;
};
static struct d3d11_resource *d3d11_resource(struct resource *r)
@@ -374,13 +375,12 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
HRESULT hr;
resource = calloc(1, sizeof(*resource));
-
- resource->r.slot = params->slot;
- resource->r.type = params->type;
+ init_resource(&resource->r, params);
switch (params->type)
{
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
{
D3D11_TEXTURE2D_DESC desc = {0};
@@ -391,7 +391,10 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
desc.Format = params->format;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ if (params->type == RESOURCE_TYPE_UAV)
+ desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
+ else
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
resource_data.pSysMem = params->data;
resource_data.SysMemPitch = params->width * params->texel_size;
@@ -399,8 +402,11 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, (ID3D11Texture2D **)&resource->resource);
ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
- hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv);
- ok(hr == S_OK, "Failed to create shader resource view, hr %#lx.\n", hr);
+ if (params->type == RESOURCE_TYPE_UAV)
+ hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, NULL, &resource->uav);
+ else
+ hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv);
+ ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr);
break;
}
@@ -420,14 +426,18 @@ static void d3d11_runner_destroy_resource(struct shader_runner *r, struct resour
ID3D11Resource_Release(resource->resource);
if (resource->srv)
ID3D11ShaderResourceView_Release(resource->srv);
+ if (resource->uav)
+ ID3D11UnorderedAccessView_Release(resource->uav);
free(resource);
}
static bool d3d11_runner_draw(struct shader_runner *r,
D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count)
{
+ ID3D11UnorderedAccessView *uavs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
ID3D11DeviceContext *context = runner->immediate_context;
+ unsigned int min_uav_slot = ARRAY_SIZE(uavs);
ID3D11Device *device = runner->device;
ID3D10Blob *vs_code, *ps_code;
ID3D11Buffer *cb = NULL;
@@ -472,6 +482,11 @@ static bool d3d11_runner_draw(struct shader_runner *r,
ID3D11DeviceContext_PSSetShaderResources(context, resource->r.slot, 1, &resource->srv);
break;
+ case RESOURCE_TYPE_UAV:
+ uavs[resource->r.slot] = resource->uav;
+ min_uav_slot = min(min_uav_slot, resource->r.slot);
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
ID3D11DeviceContext_IASetVertexBuffers(context, resource->r.slot, 1,
(ID3D11Buffer **)&resource->resource, &stride, &offset);
@@ -479,6 +494,10 @@ static bool d3d11_runner_draw(struct shader_runner *r,
}
}
+ ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context,
+ D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, NULL, NULL,
+ min_uav_slot, ARRAY_SIZE(uavs) - min_uav_slot, &uavs[min_uav_slot], NULL);
+
for (i = 0; i < runner->r.sampler_count; ++i)
{
struct sampler *sampler = &runner->r.samplers[i];
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index 22c9b2266..ec08fea54 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -79,7 +79,7 @@ static ID3D10Blob *compile_shader(const struct d3d12_shader_runner *runner, cons
return blob;
}
-#define MAX_RESOURCE_DESCRIPTORS 256
+#define MAX_RESOURCE_DESCRIPTORS (MAX_RESOURCES * 2)
static struct resource *d3d12_runner_create_resource(struct shader_runner *r, const struct resource_params *params)
{
@@ -90,9 +90,7 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co
struct d3d12_resource *resource;
resource = calloc(1, sizeof(*resource));
- resource->r.slot = params->slot;
- resource->r.type = params->type;
- resource->r.size = params->data_size;
+ init_resource(&resource->r, params);
switch (params->type)
{
@@ -101,9 +99,6 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co
runner->heap = create_gpu_descriptor_heap(device,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS);
- if (params->slot >= MAX_RESOURCE_DESCRIPTORS)
- fatal_error("Resource slot %u is too high; please increase MAX_RESOURCE_DESCRIPTORS.\n", params->slot);
-
resource->resource = create_default_texture(device, params->width, params->height,
params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST);
resource_data.pData = params->data;
@@ -116,6 +111,23 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co
NULL, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot));
break;
+ case RESOURCE_TYPE_UAV:
+ if (!runner->heap)
+ runner->heap = create_gpu_descriptor_heap(device,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS);
+
+ resource->resource = create_default_texture(device, params->width, params->height,
+ params->format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST);
+ resource_data.pData = params->data;
+ resource_data.SlicePitch = resource_data.RowPitch = params->width * params->texel_size;
+ upload_texture_data(resource->resource, &resource_data, 1, test_context->queue, test_context->list);
+ reset_command_list(test_context->list, test_context->allocator);
+ transition_resource_state(test_context->list, resource->resource,
+ D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+ ID3D12Device_CreateUnorderedAccessView(device, resource->resource,
+ NULL, NULL, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES));
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
resource->resource = create_upload_buffer(device, params->data_size, params->data);
break;
@@ -192,6 +204,7 @@ static bool d3d12_runner_draw(struct shader_runner *r,
switch (resource->r.type)
{
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
range = &resource->descriptor_range;
resource->root_index = root_signature_desc.NumParameters++;
@@ -201,7 +214,10 @@ static bool d3d12_runner_draw(struct shader_runner *r,
root_param->DescriptorTable.pDescriptorRanges = range;
root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ if (resource->r.type == RESOURCE_TYPE_UAV)
+ range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ else
+ range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
range->NumDescriptors = 1;
range->BaseShaderRegister = resource->r.slot;
range->RegisterSpace = 0;
@@ -281,6 +297,11 @@ static bool d3d12_runner_draw(struct shader_runner *r,
get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot));
break;
+ case RESOURCE_TYPE_UAV:
+ ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index,
+ get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES));
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(resource->resource);
vbv.StrideInBytes = get_vb_stride(&runner->r, resource->r.slot);
diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c
index b9ec55b4e..417d68750 100644
--- a/tests/shader_runner_d3d9.c
+++ b/tests/shader_runner_d3d9.c
@@ -222,9 +222,7 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con
void *data;
resource = calloc(1, sizeof(*resource));
- resource->r.slot = params->slot;
- resource->r.type = params->type;
- resource->r.size = params->data_size;
+ init_resource(&resource->r, params);
switch (params->type)
{
@@ -257,6 +255,10 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con
ok(hr == D3D_OK, "Failed to unmap texture, hr %#lx.\n", hr);
break;
+ case RESOURCE_TYPE_UAV:
+ fatal_error("UAVs are not supported.\n");
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
hr = IDirect3DDevice9_CreateVertexBuffer(device, params->data_size,
D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &resource->vb, NULL);
@@ -366,6 +368,10 @@ static bool d3d9_runner_draw(struct shader_runner *r,
ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr);
break;
+ case RESOURCE_TYPE_UAV:
+ assert(0);
+ break;
+
case RESOURCE_TYPE_VERTEX_BUFFER:
for (j = 0; j < runner->r.input_element_count; ++j)
{
diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c
index 601eb5a17..f5a0e7ec3 100644
--- a/tests/shader_runner_vulkan.c
+++ b/tests/shader_runner_vulkan.c
@@ -245,17 +245,25 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
void *data;
resource = calloc(1, sizeof(*resource));
-
- resource->r.slot = params->slot;
- resource->r.type = params->type;
+ init_resource(&resource->r, params);
switch (params->type)
{
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
+ {
+ VkImageUsageFlagBits usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+ VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
format = vkd3d_get_vk_format(params->format);
- resource->image = create_2d_image(runner, params->width, params->height,
- VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, format, &resource->memory);
+ if (params->type == RESOURCE_TYPE_UAV)
+ {
+ layout = VK_IMAGE_LAYOUT_GENERAL;
+ usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ }
+
+ resource->image = create_2d_image(runner, params->width, params->height, usage, format, &resource->memory);
resource->view = create_2d_image_view(runner, resource->image, format);
staging_buffer = create_buffer(runner, params->data_size,
@@ -277,14 +285,14 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
VK_CALL(vkCmdCopyBufferToImage(runner->cmd_buffer, staging_buffer, resource->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion));
- transition_image_layout(runner, resource->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout);
end_command_buffer(runner);
VK_CALL(vkFreeMemory(device, staging_memory, NULL));
VK_CALL(vkDestroyBuffer(device, staging_buffer, NULL));
break;
+ }
case RESOURCE_TYPE_VERTEX_BUFFER:
resource->buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
@@ -383,8 +391,12 @@ static bool compile_shader(const struct vulkan_shader_runner *runner, const char
break;
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
binding = &bindings[interface_info.binding_count++];
- binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
+ if (resource->r.type == RESOURCE_TYPE_UAV)
+ binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
+ else
+ binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV;
binding->register_space = 0;
binding->register_index = resource->r.slot;
binding->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL;
@@ -557,6 +569,7 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner,
switch (resource->r.type)
{
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
break;
case RESOURCE_TYPE_VERTEX_BUFFER:
@@ -662,12 +675,16 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r
break;
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
binding = &bindings[set_desc.bindingCount++];
resource->binding = binding_index++;
binding->binding = resource->binding;
- binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ if (resource->r.type == RESOURCE_TYPE_UAV)
+ binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ else
+ binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
binding->descriptorCount = 1;
binding->stageFlags = VK_SHADER_STAGE_ALL;
binding->pImmutableSamplers = NULL;
@@ -729,6 +746,7 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo
switch (resource->r.type)
{
case RESOURCE_TYPE_TEXTURE:
+ case RESOURCE_TYPE_UAV:
image_info.imageView = resource->view;
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -739,6 +757,12 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo
write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
write.pImageInfo = &image_info;
+ if (resource->r.type == RESOURCE_TYPE_UAV)
+ {
+ image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+ write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ }
+
VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL));
break;
@@ -967,7 +991,7 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
VkInstanceCreateInfo instance_desc = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
VkDeviceCreateInfo device_desc = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
VkPhysicalDeviceFeatures ret_features, features;
- VkDescriptorPoolSize descriptor_pool_sizes[2];
+ VkDescriptorPoolSize descriptor_pool_sizes[3];
VkAttachmentDescription attachment_desc = {0};
static const float queue_priority = 1.0f;
VkSubpassDescription subpass_desc = {0};
@@ -1049,7 +1073,9 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
} \
features.x = VK_TRUE
+ ENABLE_FEATURE(fragmentStoresAndAtomics);
ENABLE_FEATURE(shaderImageGatherExtended);
+ ENABLE_FEATURE(shaderStorageImageWriteWithoutFormat);
if ((vr = VK_CALL(vkCreateDevice(runner->phys_device, &device_desc, NULL, &device))))
{
@@ -1115,6 +1141,8 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
descriptor_pool_sizes[0].descriptorCount = MAX_RESOURCES;
descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
descriptor_pool_sizes[1].descriptorCount = MAX_SAMPLERS;
+ descriptor_pool_sizes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ descriptor_pool_sizes[2].descriptorCount = MAX_RESOURCES;
descriptor_pool_desc.maxSets = 1;
descriptor_pool_desc.poolSizeCount = ARRAY_SIZE(descriptor_pool_sizes);
--
2.36.1
June 8, 2022
Re: [PATCH v2 0/5] MR197: winegstreamer: Add support for zero-copy in wg_transform.
by Rémi Bernon
> Sure, conceptually it's simpler, but the callbacks make it really ugly.
> (Also the fact that it's so different from the API for the transform...)
>
> We can't exactly predict how many buffers a GStreamer pipeline needs
> (well, unless it tells us through the buffer pool config), but we don't
> necessarily need to, either; we can allocate new buffers and blit if our
> pool wasn't large enough, and just make a point of always allocating
> "enough" PE buffers in practice.
>
It seems brittle, not robust to GStreamer changes, and requires tweaking
to avoid bad cases where we would copy buffers. The general solution
is simple and I have it already implemented. I'm not going to rewrite
everything just to get rid of a callback.
> Well, sure. I just ask partly because tainting memory is not the most
> obvious way of accomplishing our goals, and I wanted to see if other
> options were considered. (Also, at this point, because of the problem
> described below.)
Yes, I have explored what could be done with a pool, I actually wanted
to use one, as it seems more natural. It just doesn't work and doesn't
help us doing anything except maybe free the released buffer
automatically.
Though if, after all, the pool cannot be safely used for zero-copy as in
the case discussed below, we also wouldn't want to free buffers. The
default pool does all this exactly as we want, depending on whether
memory has been tainted.
> If we read an entire buffer but the decoder is still holding onto the
> GstBuffer, we won't be able to "taint" it because it's not writable, but
> we'll still remove the wg_sample. Later when the decoder does free the
> GstBuffer it'll be untainted and hence can be reused. Hence the buffer
> pool will pick up that buffer instead of the zero-copy buffer we want.
If the decoder and the pipeline (it also depends on what videoconvert
decides to do) does hold on the buffers, then it will likely do it all
the time. In this case there's no point in trying the zero-copy every
time.
After a while and after enough buffers have been tried and not freed by
the pool, we won't get any more useless allocations, and we'll continue
in a mode where the buffers are just copied the normal way.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/197#note_1734
June 8, 2022
Re: [PATCH v5 0/2] MR135: Cancel asyncs queued by thread when the thread is terminated - approved
by Zebediah Figura (@zfigura)
This merge request was approved by Zebediah Figura.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/135
June 8, 2022
Re: [PATCH v2 0/5] MR197: winegstreamer: Add support for zero-copy in wg_transform.
by Zebediah Figura
On 6/8/22 17:10, Rémi Bernon (@rbernon) wrote:
>> On 6/8/22 03:37, Rémi Bernon (@rbernon) wrote:
>>>> Could we do this without the callback? Just thinking out loud, maybe
>>>> something like
>>>>
>>>> void wg_allocator_add_sample(WgAllocator *allocator,
>>>> struct wg_sample *sample);
>>>> void wg_allocator_remove_sample(WgAllocator *allocator,
>>>> struct wg_sample *sample);
>>>>
>>>> which manipulate an internal wg_sample pointer, instead of having them
>>>> access the wg_transform's sample pointer. Then
>>>> wg_allocator_remove_sample() would also end up calling
>>>> wg_allocator_release_sample().
>>>>
>>>> I suspect I'm missing something, though, given my below comment...
>>>
>>> The callback is with a future use from wg_parser in mind. In that case
>>> we would forward allocation requests to the read thread (for instance).
>>
>> Ah, in order to allocate ad-hoc samples, since we don't have the same
>> requirement for the output buffer?
>>
>> It seems plausible, but I was also inclined to avoid this from the
>> beginning due to the increased code complexity. Setting up a pool of
>> wg_samples when connecting seems like a potentially better option, for
>> instance.
>
> I don't think so, we simply cannot know how many buffer GStreamer is
> going to need. Allocating them when it requests them is the right
> solution here, it's also simpler.
Sure, conceptually it's simpler, but the callbacks make it really ugly.
(Also the fact that it's so different from the API for the transform...)
We can't exactly predict how many buffers a GStreamer pipeline needs
(well, unless it tells us through the buffer pool config), but we don't
necessarily need to, either; we can allocate new buffers and blit if our
pool wasn't large enough, and just make a point of always allocating
"enough" PE buffers in practice.
>
>
>>>> Had to look this up, but apparently the default GstBufferPool will throw
>>>> away buffers if they're modified. I thought the "empty" buffers would
>>>> pile up and never be freed, but evidently not.
>>>>
>>>> I've probably had this question answered before, but can we replace the
>>>> buffer pool itself, instead of just the allocator?
>>>
>>> We could reimplement a custom buffer pool that always free buffers, but
>>> that would be more work and still won't solve the underlying problem.
>>>
>>> The problem the allocator is solving is that some decoders don't release
>>> their buffers to the pool. The gst_buffer_is_writable check catches that
>>> and gst_buffer_replace_all_memory would fail anyway if we're not the
>>> only ones holding a ref on the buffer. So instead of discarding the data
>>> we copy it back into the buffer unix memory.
>>
>> Right, but that's the problem that the allocator is solving on unmap,
>> which is orthogonal to the "don't reuse this buffer" problem.
>>
>> I guess that overriding unmap requires having a custom allocator, so I
>> should ask if we can replace the pool *as well as* the allocator.
>
> Re-implementing a pool doesn't help anything. The default implementation
> already frees the buffers when their memory is tainted, we don't need
> anything more.
Well, sure. I just ask partly because tainting memory is not the most
obvious way of accomplishing our goals, and I wanted to see if other
options were considered. (Also, at this point, because of the problem
described below.)
>
>
>>>
>>> Later, when the decoder will eventually release the buffer to the pool,
>>> it will be untainted, and so not freed until the pool is destroyed, and
>>> reusable without going through the allocator. After a few iterations the
>>> pool has enough allocated buffers, we won't get any allocation requests
>>> anymore and our samples are never used directly and we copy the data
>>> normally.
>>>
>>
>> Actually, wait, isn't this a problem we'd be able to fix *only* by using
>> a custom pool? Why doesn't the current patch 4/5 suffer from this problem?
>
> I don't understand, it's not really a problem and the code handles that
> case with the discard_data option at the same time as it handles format
> changes and partial reads (which should not happen anyway).
>
If we read an entire buffer but the decoder is still holding onto the
GstBuffer, we won't be able to "taint" it because it's not writable, but
we'll still remove the wg_sample. Later when the decoder does free the
GstBuffer it'll be untainted and hence can be reused. Hence the buffer
pool will pick up that buffer instead of the zero-copy buffer we want.
June 8, 2022
[PATCH v4 1/1] d3drm: IDirect3DRMMeshBuilder3 Load support loading from resource
by Alistair Leslie-Hughes
From: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/d3drm/meshbuilder.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/dlls/d3drm/meshbuilder.c b/dlls/d3drm/meshbuilder.c
index 1f783baf1fe..d23e2575a6e 100644
--- a/dlls/d3drm/meshbuilder.c
+++ b/dlls/d3drm/meshbuilder.c
@@ -1462,8 +1462,10 @@ end:
static HRESULT WINAPI d3drm_mesh_builder3_Load(IDirect3DRMMeshBuilder3 *iface, void *filename,
void *name, D3DRMLOADOPTIONS loadflags, D3DRMLOADTEXTURE3CALLBACK cb, void *arg)
{
+ const DWORD supported_flags = D3DRMLOAD_FROMFILE | D3DRMLOAD_FROMRESOURCE | D3DRMLOAD_FROMMEMORY
+ | D3DRMLOAD_FROMSTREAM | D3DRMLOAD_FROMURL;
struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
- DXFILELOADOPTIONS load_options;
+ DXFILELOADOPTIONS load_options = loadflags & supported_flags;
IDirectXFile *dxfile = NULL;
IDirectXFileEnumObject *enum_object = NULL;
IDirectXFileData *data = NULL;
@@ -1476,22 +1478,10 @@ static HRESULT WINAPI d3drm_mesh_builder3_Load(IDirect3DRMMeshBuilder3 *iface, v
TRACE("iface %p, filename %p, name %p, loadflags %#lx, cb %p, arg %p.\n",
iface, filename, name, loadflags, cb, arg);
- clean_mesh_builder_data(mesh_builder);
+ if (loadflags & ~supported_flags)
+ FIXME("Unsupported flags %#lx\n", loadflags & ~supported_flags);
- if (loadflags == D3DRMLOAD_FROMMEMORY)
- {
- load_options = DXFILELOAD_FROMMEMORY;
- }
- else if (loadflags == D3DRMLOAD_FROMFILE)
- {
- load_options = DXFILELOAD_FROMFILE;
- TRACE("Loading from file %s\n", debugstr_a(filename));
- }
- else
- {
- FIXME("Load options %ld not supported yet\n", loadflags);
- return E_NOTIMPL;
- }
+ clean_mesh_builder_data(mesh_builder);
hr = DirectXFileCreate(&dxfile);
if (hr != DXFILE_OK)
@@ -1503,7 +1493,10 @@ static HRESULT WINAPI d3drm_mesh_builder3_Load(IDirect3DRMMeshBuilder3 *iface, v
hr = IDirectXFile_CreateEnumObject(dxfile, filename, load_options, &enum_object);
if (hr != DXFILE_OK)
+ {
+ WARN("Failed to create object for type %#lx\n", loadflags);
goto end;
+ }
hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
if (hr != DXFILE_OK)
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/167
June 8, 2022
[PATCH v4 0/1] MR167: d3drm: IDirect3DRMMeshBuilder3::Load support loading from resource
by Alistair Leslie-Hughes (@alesliehughes)
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
--
v4: d3drm: IDirect3DRMMeshBuilder3 Load support loading from resource
https://gitlab.winehq.org/wine/wine/-/merge_requests/167
June 8, 2022