Wine-devel
Threads by month
- ----- 2026 -----
- 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
October 2020
- 82 participants
- 799 discussions
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/dssenh/Makefile.in | 2 ++
dlls/dssenh/dssenh.rgs | 56 ++++++++++++++++++++++++++++++++++++++
dlls/dssenh/main.c | 22 +++++++++------
dlls/dssenh/rsrc.rc | 22 +++++++++++++++
dlls/dssenh/tests/dssenh.c | 5 ++--
5 files changed, 95 insertions(+), 12 deletions(-)
create mode 100644 dlls/dssenh/dssenh.rgs
create mode 100644 dlls/dssenh/rsrc.rc
diff --git a/dlls/dssenh/Makefile.in b/dlls/dssenh/Makefile.in
index 4f05beee51..8015768f99 100644
--- a/dlls/dssenh/Makefile.in
+++ b/dlls/dssenh/Makefile.in
@@ -4,3 +4,5 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
main.c
+
+RC_SRCS = rsrc.rc
diff --git a/dlls/dssenh/dssenh.rgs b/dlls/dssenh/dssenh.rgs
new file mode 100644
index 0000000000..0e9bad7c17
--- /dev/null
+++ b/dlls/dssenh/dssenh.rgs
@@ -0,0 +1,56 @@
+HKLM
+{
+ NoRemove Software
+ {
+ NoRemove Microsoft
+ {
+ NoRemove Cryptography
+ {
+ NoRemove Defaults
+ {
+ NoRemove Provider
+ {
+ ForceRemove 'Microsoft Base DSS Cryptographic Provider'
+ {
+ val 'Image Path' = s '%MODULE%'
+ val 'Type' = d 3
+ }
+ ForceRemove 'Microsoft Base DSS and Diffie-Hellman Cryptographic Provider'
+ {
+ val 'Image Path' = s '%MODULE%'
+ val 'Type' = d 13
+ }
+ ForceRemove 'Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider'
+ {
+ val 'Image Path' = s '%MODULE%'
+ val 'Type' = d 13
+ }
+ ForceRemove 'Microsoft DH SChannel Cryptographic Provider'
+ {
+ val 'Image Path' = s '%MODULE%'
+ val 'Type' = d 18
+ }
+ }
+ NoRemove 'Provider Types'
+ {
+ ForceRemove 'Type 003'
+ {
+ val 'Name' = s 'Microsoft Base DSS Cryptographic Provider'
+ val 'TypeName' = s 'DSS Signature'
+ }
+ ForceRemove 'Type 013'
+ {
+ val 'Name' = s 'Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider'
+ val 'TypeName' = s 'DSS Signature with Diffie-Hellman Key Exchange'
+ }
+ ForceRemove 'Type 018'
+ {
+ val 'Name' = s 'Microsoft DH SChannel Cryptographic Provider'
+ val 'TypeName' = s 'Diffie-Hellman SChannel'
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dlls/dssenh/main.c b/dlls/dssenh/main.c
index b8dab20751..3d5e8d97d6 100644
--- a/dlls/dssenh/main.c
+++ b/dlls/dssenh/main.c
@@ -22,8 +22,13 @@
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
+#include "objbase.h"
+#include "rpcproxy.h"
+
#include "wine/debug.h"
+static HINSTANCE instance;
+
WINE_DEFAULT_DEBUG_CHANNEL(dssenh);
BOOL WINAPI CPAcquireContext( HCRYPTPROV *ret_prov, LPSTR container, DWORD flags, PVTableProvStruc vtable )
@@ -101,11 +106,12 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
switch (fdwReason)
{
- case DLL_WINE_PREATTACH:
- return FALSE; /* prefer native version */
- case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(hinstDLL);
- break;
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+ case DLL_PROCESS_ATTACH:
+ instance = hinstDLL;
+ DisableThreadLibraryCalls(hinstDLL);
+ break;
}
return TRUE;
}
@@ -115,8 +121,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
*/
HRESULT WINAPI DllRegisterServer(void)
{
- FIXME("Not implemented.\n");
- return E_UNEXPECTED;
+ return __wine_register_resources( instance );
}
/*****************************************************
@@ -124,6 +129,5 @@ HRESULT WINAPI DllRegisterServer(void)
*/
HRESULT WINAPI DllUnregisterServer(void)
{
- FIXME("Not implemented.\n");
- return E_UNEXPECTED;
+ return __wine_unregister_resources( instance );
}
diff --git a/dlls/dssenh/rsrc.rc b/dlls/dssenh/rsrc.rc
new file mode 100644
index 0000000000..ac5ba6258e
--- /dev/null
+++ b/dlls/dssenh/rsrc.rc
@@ -0,0 +1,22 @@
+/*
+ * Resources for dssenh
+ *
+ * Copyright 2020 Hans Leidekker for CodeWeavers
+ *
+ * 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
+ */
+
+/* @makedep: dssenh.rgs */
+1 WINE_REGISTRY dssenh.rgs
diff --git a/dlls/dssenh/tests/dssenh.c b/dlls/dssenh/tests/dssenh.c
index 7a16acc679..c88fcd1466 100644
--- a/dlls/dssenh/tests/dssenh.c
+++ b/dlls/dssenh/tests/dssenh.c
@@ -54,7 +54,6 @@ static void test_acquire_context(void)
/* cannot acquire along with PROV_RSA_SIG, not compatible */
SetLastError(0xdeadbeef);
result = CryptAcquireContextA(&hProv, NULL, MS_DEF_DSS_PROV_A, PROV_RSA_SIG, 0);
- todo_wine
ok(!result && GetLastError() == NTE_PROV_TYPE_NO_MATCH,
"Expected NTE_PROV_TYPE_NO_MATCH, got %08x\n", GetLastError());
@@ -574,7 +573,7 @@ static void test_data_encryption(const struct encrypt_test *tests, int testLen)
SetLastError(0xdeadbeef);
result = CryptAcquireContextA(
&hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT);
- if(!result && GetLastError() == NTE_KEYSET_NOT_DEF)
+ if (!result)
{
skip("DSSENH is currently not available, skipping encryption tests.\n");
return;
@@ -665,7 +664,7 @@ static void test_cipher_modes(const struct ciphermode_test *tests, int testLen)
SetLastError(0xdeadbeef);
result = CryptAcquireContextA(
&hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT);
- if(!result && GetLastError() == NTE_KEYSET_NOT_DEF)
+ if (!result)
{
skip("DSSENH is currently not available, skipping block cipher mode tests.\n");
return;
--
2.28.0
2
1
[PATCH 1/5] dssenh: Add stub implementations for a couple of functions.
by Hans Leidekker 07 Oct '20
by Hans Leidekker 07 Oct '20
07 Oct '20
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/dssenh/dssenh.spec | 26 +++++++--------
dlls/dssenh/main.c | 70 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 13 deletions(-)
diff --git a/dlls/dssenh/dssenh.spec b/dlls/dssenh/dssenh.spec
index c5c2545281..e40f398681 100644
--- a/dlls/dssenh/dssenh.spec
+++ b/dlls/dssenh/dssenh.spec
@@ -1,27 +1,27 @@
-@ stub CPAcquireContext
-@ stub CPCreateHash
+@ stdcall CPAcquireContext(ptr str long ptr)
+@ stdcall CPCreateHash(ptr long ptr long ptr)
@ stub CPDecrypt
-@ stub CPDeriveKey
-@ stub CPDestroyHash
-@ stub CPDestroyKey
+@ stdcall CPDeriveKey(ptr long ptr long ptr)
+@ stdcall CPDestroyHash(ptr ptr)
+@ stdcall CPDestroyKey(ptr ptr)
@ stub CPDuplicateHash
@ stub CPDuplicateKey
@ stub CPEncrypt
-@ stub CPExportKey
-@ stub CPGenKey
+@ stdcall CPExportKey(ptr ptr ptr long long ptr ptr)
+@ stdcall CPGenKey(ptr long long ptr)
@ stub CPGenRandom
-@ stub CPGetHashParam
+@ stdcall CPGetHashParam(ptr ptr long ptr ptr long)
@ stub CPGetKeyParam
@ stub CPGetProvParam
@ stub CPGetUserKey
-@ stub CPHashData
+@ stdcall CPHashData(ptr ptr ptr long long)
@ stub CPHashSessionKey
-@ stub CPImportKey
-@ stub CPReleaseContext
+@ stdcall CPImportKey(ptr ptr long ptr long ptr)
+@ stdcall CPReleaseContext(ptr long)
@ stub CPSetHashParam
@ stub CPSetKeyParam
@ stub CPSetProvParam
-@ stub CPSignHash
-@ stub CPVerifySignature
+@ stdcall CPSignHash(ptr ptr long wstr long ptr ptr)
+@ stdcall CPVerifySignature(ptr ptr ptr long ptr wstr long)
@ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer()
diff --git a/dlls/dssenh/main.c b/dlls/dssenh/main.c
index b60b3447a3..b8dab20751 100644
--- a/dlls/dssenh/main.c
+++ b/dlls/dssenh/main.c
@@ -21,10 +21,80 @@
#include "windef.h"
#include "winbase.h"
+#include "wincrypt.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dssenh);
+BOOL WINAPI CPAcquireContext( HCRYPTPROV *ret_prov, LPSTR container, DWORD flags, PVTableProvStruc vtable )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPReleaseContext( HCRYPTPROV hprov, DWORD flags )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *ret_key )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPImportKey( HCRYPTPROV hprov, const BYTE *data, DWORD len, HCRYPTKEY hpubkey, DWORD flags,
+ HCRYPTKEY *ret_key )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPExportKey( HCRYPTPROV hprov, HCRYPTKEY hkey, HCRYPTKEY hexpkey, DWORD blobtype, DWORD flags,
+ BYTE *data, DWORD *len )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPCreateHash( HCRYPTPROV hprov, ALG_ID algid, HCRYPTKEY hkey, DWORD flags, HCRYPTHASH *ret_hash )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPDestroyHash( HCRYPTPROV hprov, HCRYPTHASH hhash )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPHashData( HCRYPTPROV hprov, HCRYPTHASH hhash, const BYTE *data, DWORD len, DWORD flags )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPGetHashParam( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD param, BYTE *data, DWORD *len, DWORD flags )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPDeriveKey( HCRYPTPROV hprov, ALG_ID algid, HCRYPTHASH hhash, DWORD flags, HCRYPTKEY *ret_key )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPSignHash( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD keyspec, const WCHAR *desc, DWORD flags, BYTE *sig,
+ DWORD *siglen )
+{
+ return FALSE;
+}
+
+BOOL WINAPI CPVerifySignature( HCRYPTPROV hprov, HCRYPTHASH hhash, const BYTE *sig, DWORD siglen, HCRYPTKEY hpubkey,
+ const WCHAR *desc, DWORD flags )
+{
+ return FALSE;
+}
+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
--
2.28.0
1
0
[PATCH 7/7] wined3d: Implement stream output queries for the Vulkan adapter.
by Henri Verbeet 07 Oct '20
by Henri Verbeet 07 Oct '20
07 Oct '20
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/context_vk.c | 10 ++++++++
dlls/wined3d/query.c | 46 ++++++++++++++++++++++++++++++++--
dlls/wined3d/wined3d_private.h | 1 +
3 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index a4e394e811f..fa5aac28fd1 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1240,6 +1240,14 @@ bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
free_pools = &context_vk->free_pipeline_statistics_query_pools;
break;
+ case WINED3D_QUERY_TYPE_SO_STATISTICS:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
+ free_pools = &context_vk->free_stream_output_statistics_query_pools;
+ break;
+
default:
FIXME("Unhandled query type %#x.\n", type);
return false;
@@ -1303,6 +1311,7 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
+ wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
heap_free(context_vk->pending_queries.queries);
heap_free(context_vk->submitted.buffers);
@@ -3159,6 +3168,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi
list_init(&context_vk->free_occlusion_query_pools);
list_init(&context_vk->free_timestamp_query_pools);
list_init(&context_vk->free_pipeline_statistics_query_pools);
+ list_init(&context_vk->free_stream_output_statistics_query_pools);
wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index bb860db4ebb..5aca4a2c5a4 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -1423,6 +1423,15 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk,
| VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
break;
+ case WINED3D_QUERY_TYPE_SO_STATISTICS:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
+ pool_info.queryType = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT;
+ pool_info.pipelineStatistics = 0;
+ break;
+
default:
FIXME("Unhandled query type %#x.\n", type);
return false;
@@ -1452,6 +1461,7 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk,
uint64_t occlusion;
uint64_t timestamp;
struct wined3d_query_data_pipeline_statistics pipeline_statistics;
+ struct wined3d_query_data_so_statistics so_statistics;
} tmp, *result;
if ((vr = VK_CALL(vkGetQueryPoolResults(device_vk->vk_device, pool_idx->pool_vk->vk_query_pool,
@@ -1491,6 +1501,15 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk,
ps_result->cs_invocations += ps_tmp->cs_invocations;
break;
+ case WINED3D_QUERY_TYPE_SO_STATISTICS:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
+ result->so_statistics.primitives_written += tmp.so_statistics.primitives_written;
+ result->so_statistics.primitives_generated += tmp.so_statistics.primitives_generated;
+ break;
+
default:
FIXME("Unhandled query type %#x.\n", query_vk->q.type);
return false;
@@ -1516,7 +1535,12 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk,
idx = query_vk->pool_idx.idx;
VK_CALL(vkCmdResetQueryPool(vk_command_buffer, pool_vk->vk_query_pool, idx, 1));
- VK_CALL(vkCmdBeginQuery(vk_command_buffer, pool_vk->vk_query_pool, idx, query_vk->control_flags));
+ if (query_vk->q.type >= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1
+ && query_vk->q.type <= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3)
+ VK_CALL(vkCmdBeginQueryIndexedEXT(vk_command_buffer, pool_vk->vk_query_pool, idx,
+ query_vk->control_flags, query_vk->q.type - WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0));
+ else
+ VK_CALL(vkCmdBeginQuery(vk_command_buffer, pool_vk->vk_query_pool, idx, query_vk->control_flags));
wined3d_context_vk_reference_query(context_vk, query_vk);
}
@@ -1530,7 +1554,12 @@ static void wined3d_query_vk_end(struct wined3d_query_vk *query_vk,
pool_vk = query_vk->pool_idx.pool_vk;
idx = query_vk->pool_idx.idx;
- VK_CALL(vkCmdEndQuery(vk_command_buffer, pool_vk->vk_query_pool, idx));
+ if (query_vk->q.type >= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1
+ && query_vk->q.type <= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3)
+ VK_CALL(vkCmdEndQueryIndexedEXT(vk_command_buffer, pool_vk->vk_query_pool,
+ idx, query_vk->q.type - WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0));
+ else
+ VK_CALL(vkCmdEndQuery(vk_command_buffer, pool_vk->vk_query_pool, idx));
}
void wined3d_query_vk_resume(struct wined3d_query_vk *query_vk, struct wined3d_context_vk *context_vk)
@@ -1803,6 +1832,19 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer
data_size = sizeof(struct wined3d_query_data_pipeline_statistics);
break;
+ case WINED3D_QUERY_TYPE_SO_STATISTICS:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
+ case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
+ if (!wined3d_adapter_vk(device->adapter)->vk_info.supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
+ {
+ WARN("Stream output queries not supported.\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ data_size = sizeof(struct wined3d_query_data_so_statistics);
+ break;
+
default:
FIXME("Unhandled query type %#x.\n", type);
return WINED3DERR_NOTAVAILABLE;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ae16545a772..d932f60fa95 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2515,6 +2515,7 @@ struct wined3d_context_vk
struct list free_occlusion_query_pools;
struct list free_timestamp_query_pools;
struct list free_pipeline_statistics_query_pools;
+ struct list free_stream_output_statistics_query_pools;
struct wined3d_retired_objects_vk retired;
struct wine_rb_tree render_passes;
--
2.20.1
1
0
07 Oct '20
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 86 +++++++++++++++++++++++++++++++---
dlls/wined3d/buffer.c | 13 ++++-
dlls/wined3d/context_vk.c | 74 +++++++++++++++++++++++++++++
dlls/wined3d/wined3d_private.h | 7 ++-
dlls/wined3d/wined3d_vk.h | 9 ++++
5 files changed, 181 insertions(+), 8 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index e589699bcd9..5c219d45d3e 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -311,6 +311,7 @@ static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_v
struct wined3d_physical_device_info
{
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features;
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
VkPhysicalDeviceFeatures2 features2;
@@ -406,6 +407,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features;
struct wined3d_physical_device_info physical_device_info;
static const float priorities[] = {1.0f};
VkPhysicalDeviceFeatures2 *features2;
@@ -429,8 +431,12 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
memset(&physical_device_info, 0, sizeof(physical_device_info));
+ xfb_features = &physical_device_info.xfb_features;
+ xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
+
vertex_divisor_features = &physical_device_info.vertex_divisor_features;
vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
+ vertex_divisor_features->pNext = xfb_features;
features2 = &physical_device_info.features2;
features2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
@@ -482,15 +488,17 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
device_vk->timestamp_bits = timestamp_bits;
device_vk->vk_info = *vk_info;
-#define LOAD_DEVICE_PFN(name) \
+#define VK_DEVICE_PFN(name) \
if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
{ \
WARN("Could not get device proc addr for '" #name "'.\n"); \
hr = E_FAIL; \
goto fail; \
}
-#define VK_DEVICE_PFN LOAD_DEVICE_PFN
+#define VK_DEVICE_EXT_PFN(name) \
+ device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name));
VK_DEVICE_FUNCS()
+#undef VK_DEVICE_EXT_PFN
#undef VK_DEVICE_PFN
if (!wined3d_allocator_init(&device_vk->allocator,
@@ -838,6 +846,11 @@ static VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT)
flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+ if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT)
+ flags |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
+ if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)
+ flags |= VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
+ | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
return flags;
}
@@ -1572,6 +1585,7 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device,
struct wined3d_context_vk *context_vk;
VkCommandBuffer vk_command_buffer;
uint32_t instance_count;
+ unsigned int i;
TRACE("device %p, state %p, parameters %p.\n", device, state, parameters);
@@ -1589,6 +1603,30 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device,
return;
}
+ if (context_vk->c.transform_feedback_active)
+ {
+ if (!context_vk->vk_so_counter_bo.vk_buffer)
+ {
+ struct wined3d_bo_vk *bo = &context_vk->vk_so_counter_bo;
+
+ if (!wined3d_context_vk_create_bo(context_vk, ARRAY_SIZE(context_vk->vk_so_counters) * sizeof(uint32_t) * 2,
+ VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo))
+ ERR("Failed to create counter BO.\n");
+ for (i = 0; i < ARRAY_SIZE(context_vk->vk_so_counters); ++i)
+ {
+ context_vk->vk_so_counters[i] = bo->vk_buffer;
+ context_vk->vk_so_offsets[i] = bo->buffer_offset + i * sizeof(uint32_t) * 2;
+ }
+ }
+
+ wined3d_context_vk_reference_bo(context_vk, &context_vk->vk_so_counter_bo);
+ if (context_vk->c.transform_feedback_paused)
+ VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer, 0, ARRAY_SIZE(context_vk->vk_so_counters),
+ context_vk->vk_so_counters, context_vk->vk_so_offsets));
+ else
+ VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer, 0, 0, NULL, NULL));
+ }
+
if (parameters->indirect)
{
struct wined3d_bo_vk *bo = &indirect_vk->bo;
@@ -1627,6 +1665,14 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device,
parameters->u.direct.start_idx, parameters->u.direct.start_instance));
}
+ if (context_vk->c.transform_feedback_active)
+ {
+ VK_CALL(vkCmdEndTransformFeedbackEXT(vk_command_buffer, 0, ARRAY_SIZE(context_vk->vk_so_counters),
+ context_vk->vk_so_counters, context_vk->vk_so_offsets));
+ context_vk->c.transform_feedback_paused = 1;
+ context_vk->c.transform_feedback_active = 0;
+ }
+
context_release(&context_vk->c);
}
@@ -1882,11 +1928,13 @@ static BOOL wined3d_init_vulkan(struct wined3d_vk_info *vk_info)
#define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
#define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
#define VK_DEVICE_PFN LOAD_INSTANCE_PFN
+#define VK_DEVICE_EXT_PFN LOAD_INSTANCE_OPT_PFN
VK_INSTANCE_FUNCS()
VK_DEVICE_FUNCS()
#undef VK_INSTANCE_PFN
#undef VK_INSTANCE_EXT_PFN
#undef VK_DEVICE_PFN
+#undef VK_DEVICE_EXT_PFN
#define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
if (!vk_ops->core_pfn) \
@@ -2087,13 +2135,25 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk
{
const char *name;
unsigned int core_since_version;
+ bool required;
}
info[] =
{
- {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u},
- {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1},
- {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1},
- {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u},
+ {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, ~0u},
+ {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u, true},
+ {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, true},
+ {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1, true},
+ {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u, true},
+ };
+
+ static const struct
+ {
+ const char *name;
+ enum wined3d_vk_extension extension;
+ }
+ map[] =
+ {
+ {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, WINED3D_VK_EXT_TRANSFORM_FEEDBACK},
};
if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
@@ -2130,6 +2190,8 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk
if (!found)
{
+ if (!info[i].required)
+ continue;
WARN("Required extension '%s' is not available.\n", info[i].name);
goto done;
}
@@ -2145,6 +2207,18 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk
}
success = true;
+ for (i = 0; i < ARRAY_SIZE(map); ++i)
+ {
+ for (j = 0; j < enable_count; ++j)
+ {
+ if (!strcmp(enabled_extensions[j], map[i].name))
+ {
+ vk_info->supported[map[i].extension] = TRUE;
+ break;
+ }
+ }
+ }
+
done:
if (success)
{
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index b32d0160cc1..f2817eeee04 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1579,11 +1579,13 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf
usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
if (bind_flags & WINED3D_BIND_SHADER_RESOURCE)
usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+ if (bind_flags & WINED3D_BIND_STREAM_OUTPUT)
+ usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
if (bind_flags & WINED3D_BIND_UNORDERED_ACCESS)
usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
if (bind_flags & WINED3D_BIND_INDIRECT_BUFFER)
usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
- if (bind_flags & (WINED3D_BIND_STREAM_OUTPUT | WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL))
+ if (bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL))
FIXME("Ignoring some bind flags %#x.\n", bind_flags);
memory_type = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
@@ -1711,9 +1713,18 @@ HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined
const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
void *parent, const struct wined3d_parent_ops *parent_ops)
{
+ const struct wined3d_vk_info *vk_info = &wined3d_adapter_vk(device->adapter)->vk_info;
+
TRACE("buffer_vk %p, device %p, desc %p, data %p, parent %p, parent_ops %p.\n",
buffer_vk, device, desc, data, parent, parent_ops);
+ if ((desc->bind_flags & WINED3D_BIND_STREAM_OUTPUT)
+ && !vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
+ {
+ WARN("The Vulkan implementation does not support transform feedback.\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
if (desc->access & WINED3D_RESOURCE_ACCESS_GPU)
buffer_vk->b.flags |= WINED3D_BUFFER_USE_BO;
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 20a4522df56..a4e394e811f 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1297,6 +1297,8 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
if (context_vk->vk_framebuffer)
VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
+ if (context_vk->vk_so_counter_bo.vk_buffer)
+ wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
wined3d_context_vk_cleanup_resources(context_vk);
wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
@@ -1466,6 +1468,7 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
wined3d_context_vk_end_current_render_pass(context_vk);
context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
context_vk->update_compute_pipeline = 1;
+ context_vk->update_stream_output = 1;
context_vk->c.update_shader_resource_bindings = 1;
context_vk->c.update_compute_shader_resource_bindings = 1;
context_vk->c.update_unordered_access_view_bindings = 1;
@@ -2238,6 +2241,51 @@ static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *co
VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
}
+static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
+ VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
+{
+ VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
+ VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
+ VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
+ const struct wined3d_stream_output *stream;
+ const VkDescriptorBufferInfo *buffer_info;
+ struct wined3d_buffer_vk *buffer_vk;
+ struct wined3d_buffer *buffer;
+ unsigned int i, first, count;
+
+ first = 0;
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
+ {
+ stream = &state->stream_output[i];
+
+ if ((buffer = stream->buffer))
+ {
+ buffer_vk = wined3d_buffer_vk(buffer);
+ buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
+ wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
+ buffers[count] = buffer_info->buffer;
+ if ((offsets[count] = stream->offset) == ~0u)
+ {
+ FIXME("Appending to stream output buffers not implemented.\n");
+ offsets[count] = 0;
+ }
+ sizes[count] = buffer_info->range - offsets[count];
+ offsets[count] += buffer_info->offset;
+ ++count;
+ continue;
+ }
+
+ if (count)
+ VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
+ first = i + 1;
+ count = 0;
+ }
+
+ if (count)
+ VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
+}
+
static VkResult wined3d_context_vk_create_descriptor_pool(struct wined3d_device_vk *device_vk,
const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
{
@@ -2892,6 +2940,21 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
}
+ if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
+ {
+ for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
+ {
+ if (!(buffer = state->stream_output[i].buffer))
+ continue;
+
+ wined3d_buffer_load(buffer, &context_vk->c, state);
+ wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
+ if (!wined3d_buffer_vk(buffer)->bo_user.valid)
+ context_vk->update_stream_output = 1;
+ }
+ context_vk->c.transform_feedback_active = 1;
+ }
+
if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
{
wined3d_buffer_load(state->index_buffer, &context_vk->c, state);
@@ -2932,6 +2995,17 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
+ if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
+ {
+ context_vk->update_stream_output = 1;
+ context_vk->c.transform_feedback_paused = 0;
+ }
+ if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
+ {
+ wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
+ context_vk->update_stream_output = 0;
+ }
+
if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
{
struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(state->index_buffer);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 778b26a6757..ae16545a772 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2465,7 +2465,8 @@ struct wined3d_context_vk
const struct wined3d_vk_info *vk_info;
uint32_t update_compute_pipeline : 1;
- uint32_t padding : 31;
+ uint32_t update_stream_output : 1;
+ uint32_t padding : 30;
struct
{
@@ -2505,6 +2506,10 @@ struct wined3d_context_vk
VkSampleCountFlagBits sample_count;
unsigned int rt_count;
+ VkBuffer vk_so_counters[WINED3D_MAX_STREAM_OUTPUT_BUFFERS];
+ VkDeviceSize vk_so_offsets[WINED3D_MAX_STREAM_OUTPUT_BUFFERS];
+ struct wined3d_bo_vk vk_so_counter_bo;
+
struct list active_queries;
struct wined3d_pending_queries_vk pending_queries;
struct list free_occlusion_query_pools;
diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h
index ae81fe945ee..0b6748ed0cf 100644
--- a/dlls/wined3d/wined3d_vk.h
+++ b/dlls/wined3d/wined3d_vk.h
@@ -172,6 +172,12 @@
VK_DEVICE_PFN(vkUnmapMemory) \
VK_DEVICE_PFN(vkUpdateDescriptorSets) \
VK_DEVICE_PFN(vkWaitForFences) \
+ /* VK_EXT_transform_feedback */ \
+ VK_DEVICE_EXT_PFN(vkCmdBeginQueryIndexedEXT) \
+ VK_DEVICE_EXT_PFN(vkCmdBeginTransformFeedbackEXT) \
+ VK_DEVICE_EXT_PFN(vkCmdBindTransformFeedbackBuffersEXT) \
+ VK_DEVICE_EXT_PFN(vkCmdEndQueryIndexedEXT) \
+ VK_DEVICE_EXT_PFN(vkCmdEndTransformFeedbackEXT) \
/* VK_KHR_swapchain */ \
VK_DEVICE_PFN(vkAcquireNextImageKHR) \
VK_DEVICE_PFN(vkCreateSwapchainKHR) \
@@ -186,11 +192,13 @@ struct vulkan_ops
#define VK_INSTANCE_PFN DECLARE_VK_PFN
#define VK_INSTANCE_EXT_PFN DECLARE_VK_PFN
#define VK_DEVICE_PFN DECLARE_VK_PFN
+#define VK_DEVICE_EXT_PFN DECLARE_VK_PFN
VK_DEVICE_FUNCS()
VK_INSTANCE_FUNCS()
#undef VK_INSTANCE_PFN
#undef VK_INSTANCE_EXT_PFN
#undef VK_DEVICE_PFN
+#undef VK_DEVICE_EXT_PFN
PFN_vkCreateInstance vkCreateInstance;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
@@ -199,6 +207,7 @@ struct vulkan_ops
enum wined3d_vk_extension
{
WINED3D_VK_EXT_NONE,
+ WINED3D_VK_EXT_TRANSFORM_FEEDBACK,
WINED3D_VK_EXT_COUNT,
};
--
2.20.1
1
0
[PATCH 5/7] wined3d: Implement vertex shader stream output in the SPIR-V shader backend.
by Henri Verbeet 07 Oct '20
by Henri Verbeet 07 Oct '20
07 Oct '20
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/shader_spirv.c | 38 ++++++++++++++++++++++++-------------
1 file changed, 25 insertions(+), 13 deletions(-)
diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c
index d729bf5c390..eb2647db12d 100644
--- a/dlls/wined3d/shader_spirv.c
+++ b/dlls/wined3d/shader_spirv.c
@@ -54,6 +54,7 @@ struct shader_spirv_resource_bindings
SIZE_T vk_bindings_size, vk_binding_count;
size_t binding_base[WINED3D_SHADER_TYPE_COUNT];
+ enum wined3d_shader_type so_stage;
};
struct shader_spirv_priv
@@ -80,6 +81,7 @@ struct shader_spirv_compile_arguments
struct shader_spirv_graphics_program_variant_vk
{
struct shader_spirv_compile_arguments compile_args;
+ const struct wined3d_stream_output_desc *so_desc;
size_t binding_base;
VkShaderModule vk_module;
@@ -276,17 +278,14 @@ static const char *get_line(const char **ptr)
}
static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_shader_interface *iface,
- struct wined3d_shader *shader, const struct shader_spirv_resource_bindings *b)
+ struct wined3d_shader *shader, const struct shader_spirv_resource_bindings *b,
+ const struct wined3d_stream_output_desc *so_desc)
{
- enum wined3d_shader_type shader_type = shader->reg_maps.shader_version.type;
-
memset(iface, 0, sizeof(*iface));
iface->vkd3d_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
- if (shader_type == WINED3D_SHADER_TYPE_GEOMETRY && shader->u.gs.so_desc)
+ if (so_desc)
{
- const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
-
iface->xfb_info.type = VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO;
iface->xfb_info.next = NULL;
@@ -307,7 +306,7 @@ static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_sh
static VkShaderModule shader_spirv_compile(struct wined3d_context_vk *context_vk,
struct wined3d_shader *shader, const struct shader_spirv_compile_arguments *args,
- const struct shader_spirv_resource_bindings *bindings)
+ const struct shader_spirv_resource_bindings *bindings, const struct wined3d_stream_output_desc *so_desc)
{
struct wined3d_shader_spirv_compile_args compile_args;
struct wined3d_shader_spirv_shader_interface iface;
@@ -322,7 +321,7 @@ static VkShaderModule shader_spirv_compile(struct wined3d_context_vk *context_vk
VkResult vr;
int ret;
- shader_spirv_init_shader_interface_vk(&iface, shader, bindings);
+ shader_spirv_init_shader_interface_vk(&iface, shader, bindings, so_desc);
shader_type = shader->reg_maps.shader_version.type;
shader_spirv_init_compile_args(&compile_args, &iface.vkd3d_interface,
VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, shader_type, args);
@@ -383,13 +382,17 @@ static struct shader_spirv_graphics_program_variant_vk *shader_spirv_find_graphi
struct shader_spirv_priv *priv, struct wined3d_context_vk *context_vk, struct wined3d_shader *shader,
const struct wined3d_state *state, const struct shader_spirv_resource_bindings *bindings)
{
- size_t binding_base = bindings->binding_base[shader->reg_maps.shader_version.type];
+ enum wined3d_shader_type shader_type = shader->reg_maps.shader_version.type;
struct shader_spirv_graphics_program_variant_vk *variant_vk;
+ size_t binding_base = bindings->binding_base[shader_type];
+ const struct wined3d_stream_output_desc *so_desc = NULL;
struct shader_spirv_graphics_program_vk *program_vk;
struct shader_spirv_compile_arguments args;
size_t variant_count, i;
shader_spirv_compile_arguments_init(&args, &context_vk->c, shader, state, context_vk->sample_count);
+ if (bindings->so_stage == shader_type)
+ so_desc = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]->u.gs.so_desc;
if (!(program_vk = shader->backend_data))
return NULL;
@@ -398,7 +401,7 @@ static struct shader_spirv_graphics_program_variant_vk *shader_spirv_find_graphi
for (i = 0; i < variant_count; ++i)
{
variant_vk = &program_vk->variants[i];
- if (variant_vk->binding_base == binding_base
+ if (variant_vk->so_desc == so_desc && variant_vk->binding_base == binding_base
&& !memcmp(&variant_vk->compile_args, &args, sizeof(args)))
return variant_vk;
}
@@ -410,7 +413,7 @@ static struct shader_spirv_graphics_program_variant_vk *shader_spirv_find_graphi
variant_vk = &program_vk->variants[variant_count];
variant_vk->compile_args = args;
variant_vk->binding_base = binding_base;
- if (!(variant_vk->vk_module = shader_spirv_compile(context_vk, shader, &args, bindings)))
+ if (!(variant_vk->vk_module = shader_spirv_compile(context_vk, shader, &args, bindings, so_desc)))
return NULL;
++program_vk->variant_count;
@@ -434,7 +437,7 @@ static struct shader_spirv_compute_program_vk *shader_spirv_find_compute_program
if (program->vk_module)
return program;
- if (!(program->vk_module = shader_spirv_compile(context_vk, shader, NULL, bindings)))
+ if (!(program->vk_module = shader_spirv_compile(context_vk, shader, NULL, bindings, NULL)))
return NULL;
if (!(layout = wined3d_context_vk_get_pipeline_layout(context_vk,
@@ -671,6 +674,7 @@ static bool shader_spirv_resource_bindings_init(struct shader_spirv_resource_bin
bindings->binding_count = 0;
bindings->uav_counter_count = 0;
bindings->vk_binding_count = 0;
+ bindings->so_stage = WINED3D_SHADER_TYPE_GEOMETRY;
wined3d_bindings->count = 0;
for (shader_type = 0; shader_type < WINED3D_SHADER_TYPE_COUNT; ++shader_type)
@@ -681,9 +685,15 @@ static bool shader_spirv_resource_bindings_init(struct shader_spirv_resource_bin
continue;
if (shader_type == WINED3D_SHADER_TYPE_COMPUTE)
+ {
descriptor_info = &((struct shader_spirv_compute_program_vk *)shader->backend_data)->descriptor_info;
+ }
else
+ {
descriptor_info = &((struct shader_spirv_graphics_program_vk *)shader->backend_data)->descriptor_info;
+ if (shader_type == WINED3D_SHADER_TYPE_GEOMETRY && !shader->function)
+ bindings->so_stage = WINED3D_SHADER_TYPE_VERTEX;
+ }
vk_stage = vk_shader_stage_from_wined3d(shader_type);
shader_visibility = vkd3d_shader_visibility_from_wined3d(shader_type);
@@ -829,6 +839,8 @@ static void shader_spirv_select(void *shader_priv, struct wined3d_context *conte
ERR("Failed to initialise shader resource bindings.\n");
goto fail;
}
+ if (context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_GEOMETRY))
+ context->shader_update_mask |= 1u << bindings->so_stage;
layout_vk = wined3d_context_vk_get_pipeline_layout(context_vk, bindings->vk_bindings, bindings->vk_binding_count);
context_vk->graphics.vk_set_layout = layout_vk->vk_set_layout;
@@ -840,7 +852,7 @@ static void shader_spirv_select(void *shader_priv, struct wined3d_context *conte
|| binding_base[shader_type] == bindings->binding_base[shader_type]))
continue;
- if (!(shader = state->shader[shader_type]))
+ if (!(shader = state->shader[shader_type]) || !shader->function)
{
context_vk->graphics.vk_modules[shader_type] = VK_NULL_HANDLE;
continue;
--
2.20.1
1
0
07 Oct '20
This allows us to compare them by pointer.
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/device.c | 54 ++++++++++++++++++++++++
dlls/wined3d/glsl_shader.c | 10 ++---
dlls/wined3d/shader.c | 77 +++++++++++++++++++++++++++-------
dlls/wined3d/shader_spirv.c | 12 +++---
dlls/wined3d/wined3d_private.h | 16 +++++--
5 files changed, 140 insertions(+), 29 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index b077d5317db..cc40125ac95 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -176,6 +176,13 @@ ULONG CDECL wined3d_device_incref(struct wined3d_device *device)
return refcount;
}
+static void device_free_so_desc(struct wine_rb_entry *entry, void *context)
+{
+ struct wined3d_so_desc_entry *s = WINE_RB_ENTRY_VALUE(entry, struct wined3d_so_desc_entry, entry);
+
+ heap_free(s);
+}
+
static void device_leftover_sampler(struct wine_rb_entry *entry, void *context)
{
struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
@@ -242,6 +249,7 @@ void wined3d_device_cleanup(struct wined3d_device *device)
wine_rb_destroy(&device->rasterizer_states, device_leftover_rasterizer_state, NULL);
wine_rb_destroy(&device->blend_states, device_leftover_blend_state, NULL);
wine_rb_destroy(&device->depth_stencil_states, device_leftover_depth_stencil_state, NULL);
+ wine_rb_destroy(&device->so_descs, device_free_so_desc, NULL);
wined3d_decref(device->wined3d);
device->wined3d = NULL;
@@ -5686,6 +5694,49 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
TRACE("Resource released.\n");
}
+static int wined3d_so_desc_compare(const void *key, const struct wine_rb_entry *entry)
+{
+ const struct wined3d_stream_output_desc *desc = &WINE_RB_ENTRY_VALUE(entry,
+ struct wined3d_so_desc_entry, entry)->desc;
+ const struct wined3d_stream_output_desc *k = key;
+ unsigned int i;
+ int ret;
+
+ if ((ret = (k->element_count - desc->element_count)))
+ return ret;
+ if ((ret = (k->buffer_stride_count - desc->buffer_stride_count)))
+ return ret;
+ if ((ret = (k->rasterizer_stream_idx - desc->rasterizer_stream_idx)))
+ return ret;
+
+ for (i = 0; i < k->element_count; ++i)
+ {
+ const struct wined3d_stream_output_element *b = &desc->elements[i];
+ const struct wined3d_stream_output_element *a = &k->elements[i];
+
+ if ((ret = (a->stream_idx - b->stream_idx)))
+ return ret;
+ if ((ret = strcmp(a->semantic_name, b->semantic_name)))
+ return ret;
+ if ((ret = (a->semantic_idx - b->semantic_idx)))
+ return ret;
+ if ((ret = (a->component_idx - b->component_idx)))
+ return ret;
+ if ((ret = (a->component_count - b->component_count)))
+ return ret;
+ if ((ret = (a->output_slot - b->output_slot)))
+ return ret;
+ }
+
+ for (i = 0; i < k->buffer_stride_count; ++i)
+ {
+ if ((ret = (k->buffer_strides[i] - desc->buffer_strides[i])))
+ return ret;
+ }
+
+ return 0;
+}
+
static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry *entry)
{
const struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
@@ -5773,6 +5824,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
fragment_pipeline = adapter->fragment_pipe;
+ wine_rb_init(&device->so_descs, wined3d_so_desc_compare);
wine_rb_init(&device->samplers, wined3d_sampler_compare);
wine_rb_init(&device->rasterizer_states, wined3d_rasterizer_state_compare);
wine_rb_init(&device->blend_states, wined3d_blend_state_compare);
@@ -5788,6 +5840,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
wine_rb_destroy(&device->rasterizer_states, NULL, NULL);
wine_rb_destroy(&device->blend_states, NULL, NULL);
wine_rb_destroy(&device->depth_stencil_states, NULL, NULL);
+ wine_rb_destroy(&device->so_descs, NULL, NULL);
wined3d_decref(device->wined3d);
return hr;
}
@@ -5815,6 +5868,7 @@ err:
wine_rb_destroy(&device->rasterizer_states, NULL, NULL);
wine_rb_destroy(&device->blend_states, NULL, NULL);
wine_rb_destroy(&device->depth_stencil_states, NULL, NULL);
+ wine_rb_destroy(&device->so_descs, NULL, NULL);
wined3d_decref(device->wined3d);
return hr;
}
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index cdc36ce77d2..7423b2003a6 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -859,7 +859,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_stri
const char **varyings, unsigned int *varying_count, char *strings, unsigned int *strings_length,
GLenum buffer_mode, struct wined3d_shader *shader)
{
- const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
+ const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
unsigned int buffer_idx, count, length, highest_output_slot, stride;
unsigned int i, register_idx, component_idx;
BOOL have_varyings_to_record = FALSE;
@@ -948,7 +948,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_stri
static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl *context_gl,
struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader)
{
- const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
+ const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
const struct wined3d_gl_info *gl_info = context_gl->gl_info;
struct wined3d_string_buffer *buffer;
unsigned int i, count, length;
@@ -956,7 +956,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl
char *strings;
GLenum mode;
- if (!so_desc->element_count)
+ if (!so_desc)
return;
if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
@@ -1005,7 +1005,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl
if (!shader_glsl_generate_transform_feedback_varyings(buffer, NULL, &count, NULL, &length, mode, shader))
{
FIXME("No varyings to record, disabling transform feedback.\n");
- shader->u.gs.so_desc.element_count = 0;
+ shader->u.gs.so_desc = NULL;
string_buffer_release(&priv->string_buffers, buffer);
return;
}
@@ -7217,7 +7217,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
static void shader_glsl_generate_stream_output_setup(struct wined3d_string_buffer *buffer,
const struct wined3d_shader *shader)
{
- const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
+ const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
unsigned int i, register_idx, component_idx;
shader_addline(buffer, "out shader_in_out\n{\n");
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index d3921d5a981..8843e6883fc 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -3137,10 +3137,6 @@ static void shader_cleanup(struct wined3d_shader *shader)
heap_free(shader->u.hs.phases.fork);
heap_free(shader->u.hs.phases.join);
}
- else if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
- {
- heap_free((void *)shader->u.gs.so_desc.elements);
- }
heap_free(shader->patch_constant_signature.elements);
heap_free(shader->output_signature.elements);
@@ -3749,13 +3745,67 @@ BOOL shader_get_stream_output_register_info(const struct wined3d_shader *shader,
return TRUE;
}
+static HRESULT geometry_shader_init_so_desc(struct wined3d_geometry_shader *gs, struct wined3d_device *device,
+ const struct wined3d_stream_output_desc *so_desc)
+{
+ struct wined3d_so_desc_entry *s;
+ struct wine_rb_entry *entry;
+ unsigned int i;
+ size_t size;
+ char *name;
+
+ if ((entry = wine_rb_get(&device->so_descs, so_desc)))
+ {
+ gs->so_desc = &WINE_RB_ENTRY_VALUE(entry, struct wined3d_so_desc_entry, entry)->desc;
+ return WINED3D_OK;
+ }
+
+ size = FIELD_OFFSET(struct wined3d_so_desc_entry, elements[so_desc->element_count]);
+ for (i = 0; i < so_desc->element_count; ++i)
+ {
+ const char *n = so_desc->elements[i].semantic_name;
+
+ if (n)
+ size += strlen(n) + 1;
+ }
+ if (!(s = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+
+ s->desc = *so_desc;
+
+ memcpy(s->elements, so_desc->elements, so_desc->element_count * sizeof(*s->elements));
+ s->desc.elements = s->elements;
+
+ name = (char *)&s->elements[s->desc.element_count];
+ for (i = 0; i < so_desc->element_count; ++i)
+ {
+ struct wined3d_stream_output_element *e = &s->elements[i];
+
+ if (!e->semantic_name)
+ continue;
+
+ size = strlen(e->semantic_name) + 1;
+ memcpy(name, e->semantic_name, size);
+ e->semantic_name = name;
+ name += size;
+ }
+
+ if (wine_rb_put(&device->so_descs, &s->desc, &s->entry) == -1)
+ {
+ heap_free(s);
+ return E_FAIL;
+ }
+ gs->so_desc = &s->desc;
+
+ return WINED3D_OK;
+}
+
static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
const struct wined3d_stream_output_desc *so_desc)
{
const struct wined3d_shader_frontend *fe = shader->frontend;
const struct wined3d_shader_signature_element *output;
unsigned int i, component_idx, register_idx, mask;
- struct wined3d_stream_output_element *elements;
struct wined3d_shader_version shader_version;
const DWORD *ptr;
void *fe_data;
@@ -3795,16 +3845,9 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return hr;
}
- if (!(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
- return E_OUTOFMEMORY;
-
- shader->u.gs.so_desc = *so_desc;
- shader->u.gs.so_desc.elements = elements;
- memcpy(elements, so_desc->elements, so_desc->element_count * sizeof(*elements));
-
for (i = 0; i < so_desc->element_count; ++i)
{
- struct wined3d_stream_output_element *e = &elements[i];
+ const struct wined3d_stream_output_element *e = &so_desc->elements[i];
if (!e->semantic_name)
continue;
@@ -3816,8 +3859,6 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return E_INVALIDARG;
}
- e->semantic_name = output->semantic_name;
-
mask = ((1u << e->component_count) - 1) << component_idx;
if ((output->mask & 0xff & mask) != mask)
{
@@ -3827,6 +3868,12 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
}
}
+ if (FAILED(hr = geometry_shader_init_so_desc(&shader->u.gs, shader->device, so_desc)))
+ {
+ WARN("Failed to initialise stream output description, hr %#x.\n", hr);
+ return hr;
+ }
+
return WINED3D_OK;
}
diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c
index 974fdab14eb..d729bf5c390 100644
--- a/dlls/wined3d/shader_spirv.c
+++ b/dlls/wined3d/shader_spirv.c
@@ -283,15 +283,17 @@ static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_sh
memset(iface, 0, sizeof(*iface));
iface->vkd3d_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
- if (shader_type == WINED3D_SHADER_TYPE_GEOMETRY && shader->u.gs.so_desc.element_count)
+ if (shader_type == WINED3D_SHADER_TYPE_GEOMETRY && shader->u.gs.so_desc)
{
+ const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
+
iface->xfb_info.type = VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO;
iface->xfb_info.next = NULL;
- iface->xfb_info.elements = (const struct vkd3d_shader_transform_feedback_element *)shader->u.gs.so_desc.elements;
- iface->xfb_info.element_count = shader->u.gs.so_desc.element_count;
- iface->xfb_info.buffer_strides = shader->u.gs.so_desc.buffer_strides;
- iface->xfb_info.buffer_stride_count = shader->u.gs.so_desc.buffer_stride_count;
+ iface->xfb_info.elements = (const struct vkd3d_shader_transform_feedback_element *)so_desc->elements;
+ iface->xfb_info.element_count = so_desc->element_count;
+ iface->xfb_info.buffer_strides = so_desc->buffer_strides;
+ iface->xfb_info.buffer_stride_count = so_desc->buffer_stride_count;
iface->vkd3d_interface.next = &iface->xfb_info;
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a4ab61b186b..778b26a6757 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3671,6 +3671,13 @@ struct wined3d_dummy_textures
* wined3d_device_create() ignores it. */
#define WINED3DCREATE_MULTITHREADED 0x00000004
+struct wined3d_so_desc_entry
+{
+ struct wine_rb_entry entry;
+ struct wined3d_stream_output_desc desc;
+ struct wined3d_stream_output_element elements[1];
+};
+
struct wined3d_device
{
LONG ref;
@@ -3715,6 +3722,7 @@ struct wined3d_device
struct list resources; /* a linked list to track resources created by the device */
struct list shaders; /* a linked list to track shaders (pixel and vertex) */
+ struct wine_rb_tree so_descs;
struct wine_rb_tree samplers, rasterizer_states, blend_states, depth_stencil_states;
/* Render Target Support */
@@ -5327,7 +5335,7 @@ struct wined3d_geometry_shader
unsigned int vertices_out;
unsigned int instance_count;
- struct wined3d_stream_output_desc so_desc;
+ const struct wined3d_stream_output_desc *so_desc;
};
struct wined3d_pixel_shader
@@ -5723,7 +5731,7 @@ static inline BOOL use_transform_feedback(const struct wined3d_state *state)
if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]))
return FALSE;
- return shader->u.gs.so_desc.element_count;
+ return !!shader->u.gs.so_desc;
}
static inline void context_apply_state(struct wined3d_context *context,
@@ -5787,8 +5795,8 @@ static inline BOOL can_use_texture_swizzle(const struct wined3d_d3d_info *d3d_in
static inline BOOL is_rasterization_disabled(const struct wined3d_shader *geometry_shader)
{
- return geometry_shader
- && geometry_shader->u.gs.so_desc.rasterizer_stream_idx == WINED3D_NO_RASTERIZER_STREAM;
+ return geometry_shader && geometry_shader->u.gs.so_desc
+ && geometry_shader->u.gs.so_desc->rasterizer_stream_idx == WINED3D_NO_RASTERIZER_STREAM;
}
static inline DWORD wined3d_extract_bits(const DWORD *bitstream,
--
2.20.1
1
0
[PATCH 3/7] wined3d: Initialise the list of Vulkan device extensions during adapter initialisation.
by Henri Verbeet 07 Oct '20
by Henri Verbeet 07 Oct '20
07 Oct '20
There's no reason to wait until wined3d device creation.
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 174 ++++++++++++++++++---------------
dlls/wined3d/wined3d_private.h | 2 +
2 files changed, 99 insertions(+), 77 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 799ec2601e6..e589699bcd9 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -274,6 +274,7 @@ static void adapter_vk_destroy(struct wined3d_adapter *adapter)
VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
wined3d_unload_vulkan(vk_info);
wined3d_adapter_cleanup(&adapter_vk->a);
+ heap_free(adapter_vk->device_extensions);
heap_free(adapter_vk);
}
@@ -397,82 +398,12 @@ static const struct wined3d_allocator_ops wined3d_allocator_vk_ops =
.allocator_destroy_chunk = wined3d_allocator_vk_destroy_chunk,
};
-static const struct
-{
- const char *name;
- unsigned int core_since_version;
-}
-vulkan_device_extensions[] =
-{
- {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u},
- {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1},
- {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1},
- {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u},
-};
-
-static bool enable_vulkan_device_extensions(VkPhysicalDevice physical_device, uint32_t *extension_count,
- const char *enabled_extensions[], const struct wined3d_vk_info *vk_info)
-{
- VkExtensionProperties *extensions = NULL;
- bool success = false, found;
- unsigned int i, j, count;
- VkResult vr;
-
- *extension_count = 0;
-
- if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
- {
- ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
- goto done;
- }
- if (!(extensions = heap_calloc(count, sizeof(*extensions))))
- {
- WARN("Out of memory.\n");
- goto done;
- }
- if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0)
- {
- ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
- goto done;
- }
-
- for (i = 0; i < ARRAY_SIZE(vulkan_device_extensions); ++i)
- {
- if (vulkan_device_extensions[i].core_since_version <= vk_info->api_version)
- continue;
-
- for (j = 0, found = false; j < count; ++j)
- {
- if (!strcmp(extensions[j].extensionName, vulkan_device_extensions[i].name))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- WARN("Required extension '%s' is not available.\n", vulkan_device_extensions[i].name);
- goto done;
- }
-
- TRACE("Enabling instance extension '%s'.\n", vulkan_device_extensions[i].name);
- enabled_extensions[(*extension_count)++] = vulkan_device_extensions[i].name;
- }
- success = true;
-
-done:
- heap_free(extensions);
- return success;
-}
-
static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
const enum wined3d_feature_level *levels, unsigned int level_count,
struct wined3d_device_parent *device_parent, struct wined3d_device **device)
{
const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk_const(adapter);
- const char *enabled_device_extensions[ARRAY_SIZE(vulkan_device_extensions)];
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
struct wined3d_physical_device_info physical_device_info;
@@ -533,13 +464,8 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
device_info.pQueueCreateInfos = &queue_info;
device_info.enabledLayerCount = 0;
device_info.ppEnabledLayerNames = NULL;
- device_info.ppEnabledExtensionNames = enabled_device_extensions;
- if (!enable_vulkan_device_extensions(physical_device,
- &device_info.enabledExtensionCount, enabled_device_extensions, vk_info))
- {
- hr = E_FAIL;
- goto fail;
- }
+ device_info.enabledExtensionCount = adapter_vk->device_extension_count;
+ device_info.ppEnabledExtensionNames = adapter_vk->device_extensions;
device_info.pEnabledFeatures = &features2->features;
if ((vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device))) < 0)
@@ -2146,6 +2072,93 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_
d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB;
}
+static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk *adapter_vk)
+{
+ VkPhysicalDevice physical_device = adapter_vk->physical_device;
+ struct wined3d_vk_info *vk_info = &adapter_vk->vk_info;
+ unsigned int count, enable_count, i, j;
+ const char **enabled_extensions = NULL;
+ VkExtensionProperties *extensions;
+ bool found, success = false;
+ SIZE_T enable_size = 0;
+ VkResult vr;
+
+ static const struct
+ {
+ const char *name;
+ unsigned int core_since_version;
+ }
+ info[] =
+ {
+ {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u},
+ {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1},
+ {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1},
+ {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u},
+ };
+
+ if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
+ {
+ ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
+ return false;
+ }
+
+ if (!(extensions = heap_calloc(count, sizeof(*extensions))))
+ {
+ ERR("Failed to allocate extension properties array.\n");
+ return false;
+ }
+
+ if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, extensions))) < 0)
+ {
+ ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr));
+ goto done;
+ }
+
+ for (i = 0, enable_count = 0; i < ARRAY_SIZE(info); ++i)
+ {
+ if (info[i].core_since_version <= vk_info->api_version)
+ continue;
+
+ for (j = 0, found = false; j < count; ++j)
+ {
+ if (!strcmp(extensions[j].extensionName, info[i].name))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ WARN("Required extension '%s' is not available.\n", info[i].name);
+ goto done;
+ }
+
+ TRACE("Enabling device extension '%s'.\n", info[i].name);
+ if (!wined3d_array_reserve((void **)&enabled_extensions, &enable_size,
+ enable_count + 1, sizeof(*enabled_extensions)))
+ {
+ ERR("Failed to allocate enabled extensions array.\n");
+ goto done;
+ }
+ enabled_extensions[enable_count++] = info[i].name;
+ }
+ success = true;
+
+done:
+ if (success)
+ {
+ adapter_vk->device_extension_count = enable_count;
+ adapter_vk->device_extensions = enabled_extensions;
+ }
+ else
+ {
+ heap_free(enabled_extensions);
+ }
+ heap_free(extensions);
+ return success;
+}
+
static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
unsigned int ordinal, unsigned int wined3d_creation_flags)
{
@@ -2167,6 +2180,9 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
if (!(adapter_vk->physical_device = get_vulkan_physical_device(vk_info)))
goto fail_vulkan;
+ if (!wined3d_adapter_vk_init_device_extensions(adapter_vk))
+ goto fail_vulkan;
+
memset(&id_properties, 0, sizeof(id_properties));
id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
@@ -2184,7 +2200,10 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
luid = (LUID *)id_properties.deviceLUID;
if (!wined3d_adapter_init(adapter, ordinal, luid, &wined3d_adapter_vk_ops))
+ {
+ heap_free(adapter_vk->device_extensions);
goto fail_vulkan;
+ }
adapter->vertex_pipe = wined3d_spirv_vertex_pipe_init_vk();
adapter->fragment_pipe = wined3d_spirv_fragment_pipe_init_vk();
@@ -2210,6 +2229,7 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk,
fail:
wined3d_adapter_cleanup(adapter);
+ heap_free(adapter_vk->device_extensions);
fail_vulkan:
VK_CALL(vkDestroyInstance(vk_info->instance, NULL));
wined3d_unload_vulkan(vk_info);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1c783d28bc2..a4ab61b186b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3347,6 +3347,8 @@ struct wined3d_adapter_vk
struct wined3d_adapter a;
struct wined3d_vk_info vk_info;
+ unsigned int device_extension_count;
+ const char **device_extensions;
VkPhysicalDevice physical_device;
VkPhysicalDeviceLimits device_limits;
--
2.20.1
1
0
[PATCH 2/7] wined3d: Implement rasteriser discard for the Vulkan adapter.
by Henri Verbeet 07 Oct '20
by Henri Verbeet 07 Oct '20
07 Oct '20
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/context_vk.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index aeb505ebfc6..20a4522df56 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1761,6 +1761,7 @@ static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_c
if (!state->rasterizer_state)
{
desc->depthClampEnable = VK_FALSE;
+ desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
desc->cullMode = VK_CULL_MODE_BACK_BIT;
desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
desc->depthBiasEnable = VK_FALSE;
@@ -1773,6 +1774,7 @@ static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_c
r = &state->rasterizer_state->desc;
desc->depthClampEnable = !r->depth_clip;
+ desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
@@ -2017,7 +2019,8 @@ static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_conte
update = true;
}
- if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
+ if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
+ || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
{
wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
--
2.20.1
1
0
[PATCH 1/7] wined3d: Copy the correct "binding_base" size in shader_spirv_select().
by Henri Verbeet 07 Oct '20
by Henri Verbeet 07 Oct '20
07 Oct '20
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/shader_spirv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c
index a4368a944ab..974fdab14eb 100644
--- a/dlls/wined3d/shader_spirv.c
+++ b/dlls/wined3d/shader_spirv.c
@@ -820,7 +820,7 @@ static void shader_spirv_select(void *shader_priv, struct wined3d_context *conte
priv->fragment_pipe->fp_enable(context, !use_ps(state));
bindings = &priv->bindings;
- memcpy(binding_base, bindings->binding_base, sizeof(bindings));
+ memcpy(binding_base, bindings->binding_base, sizeof(bindings->binding_base));
if (!shader_spirv_resource_bindings_init(bindings, &context_vk->graphics.bindings,
state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE)))
{
--
2.20.1
1
0
[PATCH] qedit: Block in the Null Renderer during rendering when paused.
by Gabriel Ivăncescu 07 Oct '20
by Gabriel Ivăncescu 07 Oct '20
07 Oct '20
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/qedit/nullrenderer.c | 24 ++
dlls/qedit/tests/nullrenderer.c | 521 ++++++++++++++++++++++++++++++++
2 files changed, 545 insertions(+)
diff --git a/dlls/qedit/nullrenderer.c b/dlls/qedit/nullrenderer.c
index c64d5e2..f1dbea2 100644
--- a/dlls/qedit/nullrenderer.c
+++ b/dlls/qedit/nullrenderer.c
@@ -29,6 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(qedit);
struct null_renderer
{
struct strmbase_renderer renderer;
+ HANDLE run_event;
};
static struct null_renderer *impl_from_strmbase_renderer(struct strmbase_renderer *iface)
@@ -41,7 +42,14 @@ static HRESULT WINAPI NullRenderer_DoRenderSample(struct strmbase_renderer *ifac
struct null_renderer *filter = impl_from_strmbase_renderer(iface);
if (filter->renderer.filter.state == State_Paused)
+ {
+ const HANDLE events[2] = { filter->run_event, filter->renderer.flush_event };
+
SetEvent(filter->renderer.state_event);
+ LeaveCriticalSection(&filter->renderer.csRenderLock);
+ WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ EnterCriticalSection(&filter->renderer.csRenderLock);
+ }
return S_OK;
}
@@ -56,14 +64,29 @@ static void null_renderer_destroy(struct strmbase_renderer *iface)
{
struct null_renderer *filter = impl_from_strmbase_renderer(iface);
+ CloseHandle(filter->run_event);
strmbase_renderer_cleanup(&filter->renderer);
free(filter);
}
+static void null_renderer_start_stream(struct strmbase_renderer *iface)
+{
+ struct null_renderer *filter = impl_from_strmbase_renderer(iface);
+ SetEvent(filter->run_event);
+}
+
+static void null_renderer_stop_stream(struct strmbase_renderer *iface)
+{
+ struct null_renderer *filter = impl_from_strmbase_renderer(iface);
+ ResetEvent(filter->run_event);
+}
+
static const struct strmbase_renderer_ops renderer_ops =
{
.pfnCheckMediaType = NullRenderer_CheckMediaType,
.pfnDoRenderSample = NullRenderer_DoRenderSample,
+ .renderer_start_stream = null_renderer_start_stream,
+ .renderer_stop_stream = null_renderer_stop_stream,
.renderer_destroy = null_renderer_destroy,
};
@@ -75,6 +98,7 @@ HRESULT null_renderer_create(IUnknown *outer, IUnknown **out)
return E_OUTOFMEMORY;
strmbase_renderer_init(&object->renderer, outer, &CLSID_NullRenderer, L"In", &renderer_ops);
+ object->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
TRACE("Created null renderer %p.\n", object);
*out = &object->renderer.filter.IUnknown_inner;
diff --git a/dlls/qedit/tests/nullrenderer.c b/dlls/qedit/tests/nullrenderer.c
index 8f26e47..01fda46 100644
--- a/dlls/qedit/tests/nullrenderer.c
+++ b/dlls/qedit/tests/nullrenderer.c
@@ -20,6 +20,7 @@
#define COBJMACROS
#include "dshow.h"
+#include "wine/strmbase.h"
#include "wine/test.h"
static IBaseFilter *create_null_renderer(void)
@@ -420,6 +421,525 @@ static void test_enum_media_types(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+struct testfilter
+{
+ struct strmbase_filter filter;
+ struct strmbase_source source;
+ IMediaSeeking IMediaSeeking_iface;
+};
+
+static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface)
+{
+ return CONTAINING_RECORD(iface, struct testfilter, filter);
+}
+
+static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index)
+{
+ struct testfilter *filter = impl_from_strmbase_filter(iface);
+
+ return index ? NULL : &filter->source.pin;
+}
+
+static void testfilter_destroy(struct strmbase_filter *iface)
+{
+ struct testfilter *filter = impl_from_strmbase_filter(iface);
+
+ strmbase_source_cleanup(&filter->source);
+ strmbase_filter_cleanup(&filter->filter);
+}
+
+static HRESULT testfilter_init_stream(struct strmbase_filter *iface)
+{
+ struct testfilter *filter = impl_from_strmbase_filter(iface);
+ HRESULT hr;
+
+ hr = BaseOutputPinImpl_Active(&filter->source);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ return hr;
+}
+
+static HRESULT testfilter_cleanup_stream(struct strmbase_filter *iface)
+{
+ struct testfilter *filter = impl_from_strmbase_filter(iface);
+ HRESULT hr;
+
+ hr = BaseOutputPinImpl_Inactive(&filter->source);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ return hr;
+}
+
+static const struct strmbase_filter_ops testfilter_ops =
+{
+ .filter_get_pin = testfilter_get_pin,
+ .filter_destroy = testfilter_destroy,
+ .filter_init_stream = testfilter_init_stream,
+ .filter_cleanup_stream = testfilter_cleanup_stream
+};
+
+static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt)
+{
+ static const VIDEOINFOHEADER source_format =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biWidth = 32,
+ .bmiHeader.biHeight = -16,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biBitCount = 16,
+ .bmiHeader.biCompression = BI_RGB,
+ .bmiHeader.biSizeImage = 32 * 16 * 2
+ };
+
+ if (index)
+ return S_FALSE;
+
+ mt->majortype = MEDIATYPE_Video;
+ mt->subtype = MEDIASUBTYPE_RGB565;
+ mt->bFixedSizeSamples = TRUE;
+ mt->bTemporalCompression = FALSE;
+ mt->lSampleSize = source_format.bmiHeader.biSizeImage;
+ mt->formattype = FORMAT_VideoInfo;
+ mt->pUnk = NULL;
+ mt->cbFormat = sizeof(source_format);
+ mt->pbFormat = CoTaskMemAlloc(mt->cbFormat);
+ memcpy(mt->pbFormat, &source_format, mt->cbFormat);
+ return S_OK;
+}
+
+static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
+{
+ struct testfilter *filter = impl_from_strmbase_filter(iface->filter);
+
+ if (IsEqualGUID(iid, &IID_IMediaSeeking))
+ *out = &filter->IMediaSeeking_iface;
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
+static HRESULT WINAPI testsource_DecideBufferSize(struct strmbase_source *iface,
+ IMemAllocator *allocator, ALLOCATOR_PROPERTIES *requested)
+{
+ ALLOCATOR_PROPERTIES actual;
+
+ if (!requested->cbAlign)
+ requested->cbAlign = 1;
+
+ if (requested->cbBuffer < 32 * 16 * 2)
+ requested->cbBuffer = 32 * 16 * 2;
+
+ if (!requested->cBuffers)
+ requested->cBuffers = 1;
+
+ return IMemAllocator_SetProperties(allocator, requested, &actual);
+}
+
+static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface,
+ IMemInputPin *peer, IMemAllocator **allocator)
+{
+ ALLOCATOR_PROPERTIES props = {0};
+ HRESULT hr;
+
+ hr = BaseOutputPinImpl_InitAllocator(iface, allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMemInputPin_GetAllocatorRequirements(peer, &props);
+ hr = testsource_DecideBufferSize(iface, *allocator, &props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ return IMemInputPin_NotifyAllocator(peer, *allocator, FALSE);
+}
+
+static const struct strmbase_source_ops testsource_ops =
+{
+ .base.pin_get_media_type = testsource_get_media_type,
+ .base.pin_query_interface = testsource_query_interface,
+ .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
+ .pfnDecideBufferSize = testsource_DecideBufferSize,
+ .pfnDecideAllocator = testsource_DecideAllocator
+};
+
+static struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface)
+{
+ return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface);
+}
+
+static HRESULT WINAPI testseek_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out)
+{
+ struct testfilter *filter = impl_from_IMediaSeeking(iface);
+ return IUnknown_QueryInterface(filter->filter.outer_unk, iid, out);
+}
+
+static ULONG WINAPI testseek_AddRef(IMediaSeeking *iface)
+{
+ struct testfilter *filter = impl_from_IMediaSeeking(iface);
+ return IUnknown_AddRef(filter->filter.outer_unk);
+}
+
+static ULONG WINAPI testseek_Release(IMediaSeeking *iface)
+{
+ struct testfilter *filter = impl_from_IMediaSeeking(iface);
+ return IUnknown_Release(filter->filter.outer_unk);
+}
+
+static HRESULT WINAPI testseek_GetCapabilities(IMediaSeeking *iface, DWORD *caps)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_CheckCapabilities(IMediaSeeking *iface, DWORD *caps)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
+{
+ if (winetest_debug > 1) trace("IMediaSeeking_IsFormatSupported(%s)\n", wine_dbgstr_guid(format));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetTimeFormat(IMediaSeeking *iface, GUID *format)
+{
+ if (winetest_debug > 1) trace("IMediaSeeking_GetTimeFormat()\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
+{
+ if (winetest_debug > 1) trace("IMediaSeeking_GetStopPosition()\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target,
+ const GUID *target_format, LONGLONG source, const GUID *source_format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_SetPositions(IMediaSeeking *iface, LONGLONG *current,
+ DWORD current_flags, LONGLONG *stop, DWORD stop_flags )
+{
+ if (winetest_debug > 1) trace("IMediaSeeking_SetPositions()\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_SetRate(IMediaSeeking *iface, double rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetRate(IMediaSeeking *iface, double *rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IMediaSeekingVtbl testseek_vtbl =
+{
+ testseek_QueryInterface,
+ testseek_AddRef,
+ testseek_Release,
+ testseek_GetCapabilities,
+ testseek_CheckCapabilities,
+ testseek_IsFormatSupported,
+ testseek_QueryPreferredFormat,
+ testseek_GetTimeFormat,
+ testseek_IsUsingTimeFormat,
+ testseek_SetTimeFormat,
+ testseek_GetDuration,
+ testseek_GetStopPosition,
+ testseek_GetCurrentPosition,
+ testseek_ConvertTimeFormat,
+ testseek_SetPositions,
+ testseek_GetPositions,
+ testseek_GetAvailable,
+ testseek_SetRate,
+ testseek_GetRate,
+ testseek_GetPreroll
+};
+
+static void testfilter_init(struct testfilter *filter)
+{
+ static const GUID clsid = {0xabacab};
+
+ strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
+ strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops);
+ filter->IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
+}
+
+struct frame_thread_params
+{
+ IMemInputPin *sink;
+ IMediaSample *sample;
+};
+
+static DWORD WINAPI frame_thread(void *arg)
+{
+ struct frame_thread_params *params = arg;
+ HRESULT hr;
+
+ if (winetest_debug > 1) trace("%04x: Sending frame.\n", GetCurrentThreadId());
+ hr = IMemInputPin_Receive(params->sink, params->sample);
+ if (winetest_debug > 1) trace("%04x: Returned %#x.\n", GetCurrentThreadId(), hr);
+ IMediaSample_Release(params->sample);
+ free(params);
+ return hr;
+}
+
+static HANDLE send_frame(IMemInputPin *sink)
+{
+ struct frame_thread_params *params = malloc(sizeof(*params));
+ REFERENCE_TIME start_time, end_time;
+ IMemAllocator *allocator;
+ IMediaSample *sample;
+ HANDLE thread;
+ HRESULT hr;
+ BYTE *data;
+
+ hr = IMemInputPin_GetAllocator(sink, &allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
+ if (hr == VFW_E_NOT_COMMITTED)
+ {
+ IMemAllocator_Commit(allocator);
+ hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
+ }
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaSample_GetPointer(sample, &data);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ memset(data, 0xaa, 32 * 16 * 2);
+
+ hr = IMediaSample_SetActualDataLength(sample, 32 * 16 * 2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ start_time = 0;
+ end_time = 400000;
+ hr = IMediaSample_SetTime(sample, &start_time, &end_time);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ params->sink = sink;
+ params->sample = sample;
+ thread = CreateThread(NULL, 0, frame_thread, params, 0, NULL);
+
+ IMemAllocator_Release(allocator);
+ return thread;
+}
+
+static HRESULT join_thread_(unsigned line, HANDLE thread)
+{
+ DWORD ret;
+ ok_(__FILE__, line)(!WaitForSingleObject(thread, 1000), "Wait failed.\n");
+ GetExitCodeThread(thread, &ret);
+ CloseHandle(thread);
+ return ret;
+}
+#define join_thread(thread) join_thread_(__LINE__, thread)
+
+static void test_state(void)
+{
+ IBaseFilter *renderer = create_null_renderer();
+ struct testfilter testfilter;
+ IMediaControl *control;
+ IGraphBuilder *graph;
+ OAFilterState state;
+ IMemInputPin *input;
+ IEnumPins *pins;
+ HANDLE thread;
+ HRESULT hr;
+ IPin *pin;
+
+ testfilter_init(&testfilter);
+
+ hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void**)&graph);
+ ok(hr == S_OK, "Failed to create Filter Graph: %08x.\n", hr);
+ hr = IGraphBuilder_AddFilter(graph, &testfilter.filter.IBaseFilter_iface, L"Source");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IGraphBuilder_AddFilter(graph, renderer, L"NullRenderer");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IBaseFilter_EnumPins(renderer, &pins);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IEnumPins_Next(pins, 1, &pin, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IEnumPins_Release(pins);
+
+ hr = IGraphBuilder_Connect(graph, &testfilter.source.pin.IPin_iface, pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IPin_QueryInterface(testfilter.source.pin.peer, &IID_IMemInputPin, (void**)&input);
+ ok(hr == S_OK, "QueryInterface for IID_IMemInputPin failed: %08x\n", hr);
+ hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void**)&control);
+ ok(hr == S_OK, "QueryInterface for IID_IMediaControl failed: %08x\n", hr);
+ IBaseFilter_Release(&testfilter.filter.IBaseFilter_iface);
+ IBaseFilter_Release(renderer);
+ IGraphBuilder_Release(graph);
+ IPin_Release(pin);
+
+ /* Pause should block */
+ thread = send_frame(input);
+ hr = join_thread(thread);
+ todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
+
+ thread = send_frame(input);
+
+ hr = IMediaControl_GetState(control, 1000, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = join_thread(thread);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
+
+ thread = send_frame(input);
+
+ hr = IMediaControl_GetState(control, 1000, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = join_thread(thread);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ thread = send_frame(input);
+ hr = join_thread(thread);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 0, &state);
+ todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
+
+ thread = send_frame(input);
+
+ hr = IMediaControl_GetState(control, 1000, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ /* Test flushing */
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ thread = send_frame(input);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IPin_BeginFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = join_thread(thread);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = join_thread(send_frame(input));
+ todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+ hr = IPin_EndFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 0, &state);
+ todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
+
+ thread = send_frame(input);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = join_thread(thread);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IPin_BeginFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = join_thread(send_frame(input));
+ todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+ hr = IPin_EndFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = join_thread(send_frame(input));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
START_TEST(nullrenderer)
{
IBaseFilter *filter;
@@ -443,6 +963,7 @@ START_TEST(nullrenderer)
test_aggregation();
test_media_types();
test_enum_media_types();
+ test_state();
CoUninitialize();
}
--
2.21.0
1
0