Wine-Devel
Threads by month
- ----- 2026 -----
- 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
- 8 participants
- 84547 discussions
[PATCH 3/3] ddraw: Check the foreground window in addition to the device state in ddraw_update_lost_surfaces().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
From: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
This supersedes patch 189882. Handle this in ddraw_update_lost_surfaces(),
instead of ddraw_surface7_Restore().
dlls/ddraw/ddraw.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 3cbde6ea84b..d7545e5c82c 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -4975,6 +4975,19 @@ void ddraw_update_lost_surfaces(struct ddraw *ddraw)
{
struct ddraw_surface *surface;
+ /* Railroad Tycoon 2 tries to restore surfaces from within a
+ * WM_QUERYNEWPALETTE message handler and expects it to succeed. We
+ * haven't received the WM_ACTIVATEAPP message by that point, so the
+ * device state is still DDRAW_DEVICE_STATE_LOST, even though we are in
+ * the foreground. */
+ if (ddraw->device_state == DDRAW_DEVICE_STATE_LOST)
+ {
+ HWND window = ddraw->focuswindow ? ddraw->focuswindow : ddraw->dest_window;
+
+ if (window && GetForegroundWindow() == window)
+ ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED;
+ }
+
if (ddraw->device_state != DDRAW_DEVICE_STATE_NOT_RESTORED)
return;
--
2.20.1
2
1
[PATCH] wininet: Implement INTERNET_OPTION_SECURITY_CERTIFICATE flag for InternetQueryOption.
by Daniel Lehman July 30, 2020
by Daniel Lehman July 30, 2020
July 30, 2020
Signed-off-by: Daniel Lehman <dlehman25(a)gmail.com>
---
dlls/wininet/http.c | 120 ++++++++++++++++++++++++++++++++++++++
dlls/wininet/resource.h | 3 +
dlls/wininet/tests/http.c | 112 ++++++++++++++++++++++++++++++++++-
dlls/wininet/wininet.rc | 12 ++++
4 files changed, 245 insertions(+), 2 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 56c995805b..379455fddb 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -35,6 +35,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
+#include <math.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
@@ -54,6 +55,7 @@
#include "internet.h"
#include "zlib.h"
+#include "resource.h"
#include "wine/debug.h"
#include "wine/exception.h"
@@ -2273,6 +2275,124 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
}
return ERROR_NOT_SUPPORTED;
}
+ case INTERNET_OPTION_SECURITY_CERTIFICATE: {
+ char fmt[256];
+ const char nullA[] = "(null)"; /* always appears in English */
+ CERT_CONTEXT *context;
+ char *subject = NULL;
+ char *issuer = NULL;
+ char *start_date = NULL;
+ char *start_time = NULL;
+ char *expiry_date = NULL;
+ char *expiry_time = NULL;
+ char strength[16];
+ int subject_len, issuer_len;
+ int start_date_len, start_time_len;
+ int expiry_date_len, expiry_time_len;
+ SYSTEMTIME start, expiry;
+ DWORD needed, keysize;
+
+ if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
+ FIXME("INTERNET_OPTION_SECURITY_CERTIFICATE currently English-only\n");
+
+ if(!req->netconn)
+ return ERROR_INTERNET_INVALID_OPERATION;
+
+ if(!size)
+ return ERROR_INVALID_PARAMETER;
+
+ if(!buffer) {
+ *size = 1;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ context = (CERT_CONTEXT *)NETCON_GetCert(req->netconn);
+ if(!context)
+ return ERROR_NOT_SUPPORTED;
+
+ needed = LoadStringA(WININET_hModule, IDS_CERT_FORMAT, fmt, sizeof(fmt));
+ needed += 1 - 20 * 2 + 9; /* include room for \0, subtract 20 format specifiers, add 9 \r */
+ if(needed > *size) goto error;
+
+ subject_len = CertNameToStrA(context->dwCertEncodingType, &context->pCertInfo->Subject,
+ CERT_SIMPLE_NAME_STR|CERT_NAME_STR_CRLF_FLAG, NULL, 0);
+ needed += subject_len - 1; /* minus \0 */
+ if(needed > *size) goto error;
+
+ issuer_len = CertNameToStrA(context->dwCertEncodingType, &context->pCertInfo->Issuer,
+ CERT_SIMPLE_NAME_STR|CERT_NAME_STR_CRLF_FLAG, NULL, 0);
+ needed += issuer_len - 1;
+ if(needed > *size) goto error;
+
+ FileTimeToSystemTime(&context->pCertInfo->NotBefore, &start);
+ start_date_len = GetDateFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, NULL, 0);
+ start_time_len = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, NULL, 0);
+ needed += start_date_len + start_time_len - 2;
+ if(needed > *size) goto error;
+
+ FileTimeToSystemTime(&context->pCertInfo->NotAfter, &expiry);
+ expiry_date_len = GetDateFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, NULL, 0);
+ expiry_time_len = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, NULL, 0);
+ needed += expiry_date_len + expiry_time_len - 2;
+ if(needed > *size) goto error;
+
+ needed += sizeof(nullA) * 3 - 3; /* protocol, signature type, encryption type */
+ if(needed > *size) goto error;
+
+ keysize = NETCON_GetCipherStrength(req->netconn);
+ needed += keysize ? floor(log10(keysize))+1 : 1;
+ needed += LoadStringA(WININET_hModule, keysize >= 128 ? IDS_CERT_HIGH : IDS_CERT_LOW,
+ strength, sizeof(strength));
+ if(needed > *size) goto error;
+
+ if(!(subject = heap_alloc(subject_len)) ||
+ !(issuer = heap_alloc(issuer_len)) ||
+ !(start_date = heap_alloc(start_date_len)) ||
+ !(start_time = heap_alloc(start_time_len)) ||
+ !(expiry_date = heap_alloc(expiry_date_len)) ||
+ !(expiry_time = heap_alloc(expiry_time_len)))
+ goto error;
+
+ CertNameToStrA(context->dwCertEncodingType, &context->pCertInfo->Subject,
+ CERT_SIMPLE_NAME_STR|CERT_NAME_STR_CRLF_FLAG, subject, subject_len);
+ CertNameToStrA(context->dwCertEncodingType, &context->pCertInfo->Issuer,
+ CERT_SIMPLE_NAME_STR|CERT_NAME_STR_CRLF_FLAG, issuer, issuer_len);
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_date, start_date_len);
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_time, start_time_len);
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_date, expiry_date_len);
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_time, expiry_time_len);
+
+ snprintf(buffer, *size, fmt,
+ '\r', subject, '\r',
+ '\r', issuer, '\r',
+ start_date, start_time, '\r',
+ expiry_date, expiry_time, '\r',
+ nullA, '\r',
+ nullA, '\r',
+ nullA, '\r',
+ strength, keysize);
+
+ heap_free(subject);
+ heap_free(issuer);
+ heap_free(start_date);
+ heap_free(start_time);
+ heap_free(expiry_date);
+ heap_free(expiry_time);
+ *size = needed - 1;
+ CertFreeCertificateContext(context);
+ return ERROR_SUCCESS;
+
+error:
+ heap_free(subject);
+ heap_free(issuer);
+ heap_free(start_date);
+ heap_free(start_time);
+ heap_free(expiry_date);
+ heap_free(expiry_time);
+ *size = 1;
+ CertFreeCertificateContext(context);
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
case INTERNET_OPTION_CONNECT_TIMEOUT:
if (*size < sizeof(DWORD))
return ERROR_INSUFFICIENT_BUFFER;
diff --git a/dlls/wininet/resource.h b/dlls/wininet/resource.h
index 256a374af0..190d3cc397 100644
--- a/dlls/wininet/resource.h
+++ b/dlls/wininet/resource.h
@@ -38,3 +38,6 @@
#define IDS_CERT_DATE_INVALID 0x502
#define IDS_CERT_CN_INVALID 0x503
#define IDS_CERT_ERRORS 0x504
+#define IDS_CERT_FORMAT 0x505
+#define IDS_CERT_HIGH 0x506
+#define IDS_CERT_LOW 0x507
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index c07d60d2a9..1eed1101c8 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -6112,9 +6112,26 @@ static const cert_struct_test_t test_winehq_com_cert = {
"webmaster(a)winehq.org"
};
+static const char *cert_string_fmt =
+ "Subject:\r\n%s\r\n"
+ "Issuer:\r\n%s\r\n"
+ "Effective Date:\t%s %s\r\n"
+ "Expiration Date:\t%s %s\r\n"
+ "Security Protocol:\t%s\r\n"
+ "Signature Type:\t%s\r\n"
+ "Encryption Type:\t%s\r\n"
+ "Privacy Strength:\t%s (%u bits)";
+
static void test_cert_struct(HINTERNET req, const cert_struct_test_t *test)
{
INTERNET_CERTIFICATE_INFOA info;
+ SYSTEMTIME start, expiry;
+ char expiry_date[32];
+ char expiry_time[32];
+ char start_date[32];
+ char start_time[32];
+ char expect[512];
+ char actual[512];
DWORD size;
BOOL res;
@@ -6138,6 +6155,33 @@ static void test_cert_struct(HINTERNET req, const cert_struct_test_t *test)
ok(!info.lpszProtocolName, "lpszProtocolName = %s\n", info.lpszProtocolName);
ok(info.dwKeySize >= 128 && info.dwKeySize <= 256, "dwKeySize = %u\n", info.dwKeySize);
+ if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
+ {
+ skip("Non-English locale (test with hardcoded English)\n");
+ release_cert_info(&info);
+ return;
+ }
+
+ size = sizeof(actual);
+ memset(actual, 0xcc, sizeof(actual));
+ res = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE, actual, &size);
+ ok(res, "InternetQueryOption failed: %u\n", GetLastError());
+
+ FileTimeToSystemTime(&info.ftStart, &start);
+ FileTimeToSystemTime(&info.ftExpiry, &expiry);
+
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_date, sizeof(start_date));
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_time, sizeof(start_time));
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_date, sizeof(expiry_date));
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_time, sizeof(expiry_time));
+
+ snprintf(expect, sizeof(expect), cert_string_fmt, info.lpszSubjectInfo, info.lpszIssuerInfo,
+ start_date, start_time, expiry_date, expiry_time,
+ info.lpszSignatureAlgName, info.lpszEncryptionAlgName, info.lpszProtocolName,
+ info.dwKeySize >= 128 ? "High" : "Low", info.dwKeySize);
+ ok(size == strlen(actual), "size = %u\n", size);
+ ok(!strcmp(actual, expect), "cert = actual\n%s\n", actual);
+
release_cert_info(&info);
}
@@ -6217,7 +6261,7 @@ static void test_security_flags(void)
INTERNET_CERTIFICATE_INFOA *cert;
HINTERNET ses, conn, req;
DWORD size, flags;
- char buf[100];
+ char buf[512];
BOOL res;
if (!https_support)
@@ -6378,6 +6422,26 @@ static void test_security_flags(void)
}
HeapFree(GetProcessHeap(), 0, cert);
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, NULL, NULL);
+ ok(!res && GetLastError() == ERROR_INVALID_PARAMETER, "InternetQueryOption failed: %d\n", GetLastError());
+
+ size = 0;
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, NULL, &size);
+ ok(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size == 1, "unexpected size: %u\n", size);
+
+ size = 42;
+ memset(buf, 0x55, sizeof(buf));
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, buf, &size);
+ ok(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size == 1, "unexpected size: %u\n", size);
+ ok(buf[0] == 0x55, "unexpected byte: %02x\n", buf[0]);
+
+ size = sizeof(buf);
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, buf, &size);
+ ok(res && GetLastError() == ERROR_SUCCESS, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size && size < sizeof(buf), "unexpected size: %u\n", size);
+
CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTING_TO_SERVER, 2);
CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTED_TO_SERVER, 2);
CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
@@ -6562,9 +6626,10 @@ static void test_secure_connection(void)
static const WCHAR get[] = {'G','E','T',0};
static const WCHAR testpage[] = {'/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
HINTERNET ses, con, req;
- DWORD size, flags, err;
+ DWORD size, size2, flags, err;
INTERNET_CERTIFICATE_INFOA *certificate_structA = NULL;
INTERNET_CERTIFICATE_INFOW *certificate_structW = NULL;
+ char certstr1[512], certstr2[512];
BOOL ret;
ses = InternetOpenA("Gizmo5", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
@@ -6629,6 +6694,19 @@ static void test_secure_connection(void)
}
HeapFree(GetProcessHeap(), 0, certificate_structW);
+ SetLastError(0xdeadbeef);
+ size = sizeof(certstr1);
+ ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, certstr1, &size);
+ ok(ret && GetLastError() == ERROR_SUCCESS, "InternetQueryOption failed: %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ size2 = sizeof(certstr2);
+ ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE, certstr2, &size2);
+ ok(ret && GetLastError() == ERROR_SUCCESS, "InternetQueryOption failed: %d\n", GetLastError());
+
+ ok(size == size2, "expected same size\n");
+ ok(!strcmp(certstr1, certstr2), "expected same string\n");
+
InternetCloseHandle(req);
InternetCloseHandle(con);
InternetCloseHandle(ses);
@@ -7517,6 +7595,35 @@ static void test_concurrent_header_access(void)
CloseHandle( wait );
}
+static void test_cert_string(void)
+{
+ HINTERNET ses, con, req;
+ char actual[512];
+ DWORD size;
+ BOOL res;
+
+ ses = InternetOpenA( "winetest", 0, NULL, NULL, 0 );
+ ok( ses != NULL, "InternetOpenA failed\n" );
+
+ con = InternetConnectA( ses, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
+ INTERNET_SERVICE_HTTP, 0, 0 );
+ ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
+
+ req = HttpOpenRequestA( con, NULL, "/", NULL, NULL, NULL, 0, 0 );
+ ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
+
+ SetLastError(0xdeadbeef);
+ size = sizeof(actual);
+ memset(actual, 0xcc, sizeof(actual));
+ res = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE, actual, &size);
+ ok(!res && GetLastError() == ERROR_INTERNET_INVALID_OPERATION,
+ "InternetQueryOption failed: %u\n", GetLastError());
+
+ InternetCloseHandle( req );
+ InternetCloseHandle( con );
+ InternetCloseHandle( ses );
+}
+
START_TEST(http)
{
HMODULE hdll;
@@ -7566,5 +7673,6 @@ START_TEST(http)
test_connection_failure();
test_default_service_port();
test_concurrent_header_access();
+ test_cert_string();
free_events();
}
diff --git a/dlls/wininet/wininet.rc b/dlls/wininet/wininet.rc
index b6e35629ca..7e2830e7ff 100644
--- a/dlls/wininet/wininet.rc
+++ b/dlls/wininet/wininet.rc
@@ -29,6 +29,18 @@ STRINGTABLE
IDS_CERT_DATE_INVALID "The date on the certificate is invalid."
IDS_CERT_CN_INVALID "The name on the certificate does not match the site."
IDS_CERT_ERRORS "There is at least one unspecified security problem with this certificate."
+
+ /* each %c is a \r */
+ IDS_CERT_FORMAT "Subject:%c\n%s%c\n" \
+ "Issuer:%c\n%s%c\n" \
+ "Effective Date:\t%s %s%c\n" \
+ "Expiration Date:\t%s %s%c\n" \
+ "Security Protocol:\t%s%c\n" \
+ "Signature Type:\t%s%c\n" \
+ "Encryption Type:\t%s%c\n" \
+ "Privacy Strength:\t%s (%u bits)"
+ IDS_CERT_HIGH "High"
+ IDS_CERT_LOW "Low"
}
IDD_PROXYDLG DIALOG 36, 24, 220, 146
--
2.25.1
3
3
[PATCH 1/3] ddraw/tests: Test non-primary video memory surface in test_lost_device().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
From: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
This supersedes patch 189880. Minor style changes.
dlls/ddraw/tests/ddraw1.c | 99 +++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw2.c | 99 +++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw4.c | 104 +++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw7.c | 104 +++++++++++++++++++++++++++++++++++++-
4 files changed, 402 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 652e52a05c4..2fc454a6069 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -7309,8 +7309,8 @@ static void test_palette_alpha(void)
static void test_lost_device(void)
{
+ IDirectDrawSurface *sysmem_surface, *vidmem_surface;
IDirectDrawSurface *surface, *back_buffer;
- IDirectDrawSurface *sysmem_surface;
DDSURFACEDESC surface_desc;
HWND window1, window2;
IDirectDraw *ddraw;
@@ -7345,12 +7345,35 @@ static void test_lost_device(void)
hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+ surface_desc.dwWidth = 64;
+ surface_desc.dwHeight = 64;
+ surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+ surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
+ U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+ U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+ U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
+ if (FAILED(IDirectDraw_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
+ {
+ skip("Failed to create video memory surface, skipping related tests.\n");
+ vidmem_surface = NULL;
+ }
+
hr = IDirectDrawSurface_IsLost(surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(GetDesktopWindow());
ok(ret, "Failed to set foreground window.\n");
@@ -7360,6 +7383,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -7369,6 +7397,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = restore_surfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7378,6 +7411,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7388,6 +7426,11 @@ static void test_lost_device(void)
"Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK || broken(ddraw_is_warp(ddraw) && hr == DDERR_SURFACELOST), "Got unexpected hr %#x.\n", hr);
+ }
/* Trying to restore the primary will crash, probably because flippable
* surfaces can't exist in DDSCL_NORMAL. */
@@ -7398,6 +7441,8 @@ static void test_lost_device(void)
surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = restore_surfaces(ddraw);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7408,6 +7453,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -7415,6 +7465,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7422,6 +7477,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = restore_surfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7429,6 +7489,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
IDirectDrawSurface_Release(surface);
memset(&surface_desc, 0, sizeof(surface_desc));
@@ -7447,6 +7512,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7456,6 +7526,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7465,6 +7540,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7474,6 +7554,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7483,6 +7568,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -7492,6 +7582,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
memset(&caps, 0, sizeof(caps));
caps.dwCaps = DDSCAPS_FLIP;
@@ -7506,6 +7601,8 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
IDirectDrawSurface_Release(back_buffer);
+ if (vidmem_surface)
+ IDirectDrawSurface_Release(vidmem_surface);
IDirectDrawSurface_Release(sysmem_surface);
IDirectDrawSurface_Release(surface);
refcount = IDirectDraw_Release(ddraw);
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index edaf868900c..311c7a159df 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -8262,8 +8262,8 @@ static void test_palette_alpha(void)
static void test_lost_device(void)
{
+ IDirectDrawSurface *sysmem_surface, *vidmem_surface;
IDirectDrawSurface *surface, *back_buffer;
- IDirectDrawSurface *sysmem_surface;
DDSURFACEDESC surface_desc;
HWND window1, window2;
IDirectDraw2 *ddraw;
@@ -8298,12 +8298,35 @@ static void test_lost_device(void)
hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+ surface_desc.dwWidth = 64;
+ surface_desc.dwHeight = 64;
+ surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+ surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
+ U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+ U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+ U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
+ if (FAILED(IDirectDraw2_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
+ {
+ skip("Failed to create video memory surface, skipping related tests.\n");
+ vidmem_surface = NULL;
+ }
+
hr = IDirectDrawSurface_IsLost(surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(GetDesktopWindow());
ok(ret, "Failed to set foreground window.\n");
@@ -8313,6 +8336,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -8322,6 +8350,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = restore_surfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8331,6 +8364,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8340,6 +8378,11 @@ static void test_lost_device(void)
todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
/* Trying to restore the primary will crash, probably because flippable
* surfaces can't exist in DDSCL_NORMAL. */
@@ -8350,6 +8393,8 @@ static void test_lost_device(void)
surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = restore_surfaces(ddraw);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8360,6 +8405,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -8367,6 +8417,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8374,6 +8429,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = restore_surfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8381,6 +8441,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
IDirectDrawSurface_Release(surface);
memset(&surface_desc, 0, sizeof(surface_desc));
@@ -8399,6 +8464,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8408,6 +8478,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8417,6 +8492,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8426,6 +8506,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8435,6 +8520,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -8444,6 +8534,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
memset(&caps, 0, sizeof(caps));
caps.dwCaps = DDSCAPS_FLIP;
@@ -8458,6 +8553,8 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
IDirectDrawSurface_Release(back_buffer);
+ if (vidmem_surface)
+ IDirectDrawSurface_Release(vidmem_surface);
IDirectDrawSurface_Release(sysmem_surface);
IDirectDrawSurface_Release(surface);
refcount = IDirectDraw2_Release(ddraw);
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index d1abde05ca0..8eee655bba4 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -9655,8 +9655,8 @@ static void test_vb_writeonly(void)
static void test_lost_device(void)
{
+ IDirectDrawSurface4 *sysmem_surface, *vidmem_surface;
IDirectDrawSurface4 *surface, *back_buffer;
- IDirectDrawSurface4 *sysmem_surface;
DDSURFACEDESC2 surface_desc;
HWND window1, window2;
IDirectDraw4 *ddraw;
@@ -9691,6 +9691,24 @@ static void test_lost_device(void)
hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+ surface_desc.dwWidth = 64;
+ surface_desc.dwHeight = 64;
+ U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
+ U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
+ U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+ U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+ U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
+ if (FAILED(IDirectDraw4_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
+ {
+ skip("Failed to create video memory surface, skipping related tests.\n");
+ vidmem_surface = NULL;
+ }
+
hr = IDirectDraw4_TestCooperativeLevel(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(surface);
@@ -9699,6 +9717,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(GetDesktopWindow());
ok(ret, "Failed to set foreground window.\n");
@@ -9710,6 +9733,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -9721,6 +9749,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9732,6 +9765,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9743,6 +9781,11 @@ static void test_lost_device(void)
todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
/* Trying to restore the primary will crash, probably because flippable
* surfaces can't exist in DDSCL_NORMAL. */
@@ -9753,6 +9796,8 @@ static void test_lost_device(void)
surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw4_TestCooperativeLevel(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9760,6 +9805,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(GetDesktopWindow());
ok(ret, "Failed to set foreground window.\n");
@@ -9769,6 +9819,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -9778,6 +9833,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9787,6 +9847,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9796,6 +9861,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
IDirectDrawSurface4_Release(surface);
memset(&surface_desc, 0, sizeof(surface_desc));
@@ -9816,6 +9886,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9827,6 +9902,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9838,6 +9918,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9849,6 +9934,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9860,6 +9950,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9869,6 +9964,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface4_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface4_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT);
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
@@ -9886,6 +9986,8 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
IDirectDrawSurface4_Release(back_buffer);
+ if (vidmem_surface)
+ IDirectDrawSurface4_Release(vidmem_surface);
IDirectDrawSurface4_Release(sysmem_surface);
IDirectDrawSurface4_Release(surface);
refcount = IDirectDraw4_Release(ddraw);
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 13eadfdf132..778b1738fa9 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -9413,8 +9413,8 @@ static void test_vb_writeonly(void)
static void test_lost_device(void)
{
+ IDirectDrawSurface7 *sysmem_surface, *vidmem_surface;
IDirectDrawSurface7 *surface, *back_buffer;
- IDirectDrawSurface7 *sysmem_surface;
DDSURFACEDESC2 surface_desc;
HWND window1, window2;
IDirectDraw7 *ddraw;
@@ -9449,6 +9449,24 @@ static void test_lost_device(void)
hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+ surface_desc.dwWidth = 64;
+ surface_desc.dwHeight = 64;
+ U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
+ U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
+ U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
+ U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+ U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+ U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
+ if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
+ {
+ skip("Failed to create video memory surface, skipping related tests.\n");
+ vidmem_surface = NULL;
+ }
+
hr = IDirectDraw7_TestCooperativeLevel(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(surface);
@@ -9457,6 +9475,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(GetDesktopWindow());
ok(ret, "Failed to set foreground window.\n");
@@ -9468,6 +9491,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -9479,6 +9507,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9490,6 +9523,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9501,6 +9539,11 @@ static void test_lost_device(void)
todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
/* Trying to restore the primary will crash, probably because flippable
* surfaces can't exist in DDSCL_NORMAL. */
@@ -9513,6 +9556,8 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDraw7_TestCooperativeLevel(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9520,6 +9565,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(GetDesktopWindow());
ok(ret, "Failed to set foreground window.\n");
@@ -9529,6 +9579,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
ret = SetForegroundWindow(window1);
ok(ret, "Failed to set foreground window.\n");
@@ -9538,6 +9593,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9547,6 +9607,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9556,6 +9621,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
IDirectDrawSurface7_Release(surface);
memset(&surface_desc, 0, sizeof(surface_desc));
@@ -9576,6 +9646,11 @@ static void test_lost_device(void)
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9587,6 +9662,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9598,6 +9678,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9609,6 +9694,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9620,6 +9710,11 @@ static void test_lost_device(void)
ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ }
hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
@@ -9631,6 +9726,11 @@ static void test_lost_device(void)
ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawSurface7_IsLost(sysmem_surface);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
+ if (vidmem_surface)
+ {
+ hr = IDirectDrawSurface7_IsLost(vidmem_surface);
+ ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+ }
memset(&caps, 0, sizeof(caps));
caps.dwCaps = DDSCAPS_FLIP;
@@ -9646,6 +9746,8 @@ static void test_lost_device(void)
IDirectDrawSurface7_Release(back_buffer);
+ if (vidmem_surface)
+ IDirectDrawSurface7_Release(vidmem_surface);
IDirectDrawSurface7_Release(sysmem_surface);
IDirectDrawSurface7_Release(surface);
refcount = IDirectDraw7_Release(ddraw);
--
2.20.1
2
1
July 30, 2020
2
1
[PATCH vkd3d 5/5] vkd3d-shader: Report error messages from vkd3d_shader_serialize_root_signature().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
include/vkd3d_shader.h | 6 +-
libs/vkd3d-shader/dxbc.c | 221 +++++++++++++++++++++----------
libs/vkd3d-shader/vkd3d_shader_private.h | 21 ++-
libs/vkd3d/vkd3d_main.c | 26 +++-
tests/vkd3d_shader_api.c | 2 +-
5 files changed, 192 insertions(+), 84 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 8ee6724..140744c 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -756,9 +756,8 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages);
void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signature_desc *root_signature);
-/* FIXME: Add support for returning error messages (ID3DBlob). */
int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_root_signature_desc *root_signature,
- struct vkd3d_shader_code *dxbc);
+ struct vkd3d_shader_code *dxbc, char **messages);
int vkd3d_shader_convert_root_signature(struct vkd3d_shader_versioned_root_signature_desc *dst,
enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src);
@@ -788,7 +787,8 @@ typedef int (*PFN_vkd3d_shader_parse_root_signature)(const struct vkd3d_shader_c
typedef void (*PFN_vkd3d_shader_free_root_signature)(struct vkd3d_shader_versioned_root_signature_desc *root_signature);
typedef int (*PFN_vkd3d_shader_serialize_root_signature)(
- const struct vkd3d_shader_versioned_root_signature_desc *root_signature, struct vkd3d_shader_code *dxbc);
+ const struct vkd3d_shader_versioned_root_signature_desc *root_signature,
+ struct vkd3d_shader_code *dxbc, char **messages);
typedef int (*PFN_vkd3d_shader_convert_root_signature)(struct vkd3d_shader_versioned_root_signature_desc *dst,
enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src);
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index 28159a9..df5f6a2 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -2768,6 +2768,8 @@ static unsigned int versioned_root_signature_get_flags(const struct vkd3d_shader
struct root_signature_writer_context
{
+ struct vkd3d_shader_message_context message_context;
+
DWORD *data;
size_t position;
size_t capacity;
@@ -2813,33 +2815,38 @@ static size_t get_chunk_offset(struct root_signature_writer_context *context)
static int shader_write_root_signature_header(struct root_signature_writer_context *context)
{
if (!write_dword(context, TAG_DXBC))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
/* The checksum is computed when all data is generated. */
if (!write_dwords(context, 4, 0x00000000))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, 0x00000001))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
context->total_size_position = context->position;
if (!write_dword(context, 0xffffffff)) /* total size */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, 1)) /* chunk count */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
/* chunk offset */
if (!write_dword(context, (context->position + 1) * sizeof(DWORD)))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, TAG_RTS0))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, 0xffffffff)) /* chunk size */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
context->chunk_position = context->position;
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature header.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_descriptor_ranges(struct root_signature_writer_context *context,
@@ -2851,18 +2858,23 @@ static int shader_write_descriptor_ranges(struct root_signature_writer_context *
for (i = 0; i < table->descriptor_range_count; ++i)
{
if (!write_dword(context, ranges[i].range_type))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].descriptor_count))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].base_shader_register))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].register_space))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].descriptor_table_offset))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
}
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature descriptor ranges.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_descriptor_ranges1(struct root_signature_writer_context *context,
@@ -2874,79 +2886,109 @@ static int shader_write_descriptor_ranges1(struct root_signature_writer_context
for (i = 0; i < table->descriptor_range_count; ++i)
{
if (!write_dword(context, ranges[i].range_type))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].descriptor_count))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].base_shader_register))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].register_space))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].flags))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, ranges[i].descriptor_table_offset))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
}
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature descriptor ranges.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_descriptor_table(struct root_signature_writer_context *context,
const struct vkd3d_shader_root_descriptor_table *table)
{
if (!write_dword(context, table->descriptor_range_count))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, get_chunk_offset(context) + sizeof(DWORD))) /* offset */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
return shader_write_descriptor_ranges(context, table);
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor table.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_descriptor_table1(struct root_signature_writer_context *context,
const struct vkd3d_shader_root_descriptor_table1 *table)
{
if (!write_dword(context, table->descriptor_range_count))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, get_chunk_offset(context) + sizeof(DWORD))) /* offset */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
return shader_write_descriptor_ranges1(context, table);
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor table.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_root_constants(struct root_signature_writer_context *context,
const struct vkd3d_shader_root_constants *constants)
{
if (!write_dword(context, constants->shader_register))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, constants->register_space))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, constants->value_count))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root constants.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_root_descriptor(struct root_signature_writer_context *context,
const struct vkd3d_shader_root_descriptor *descriptor)
{
if (!write_dword(context, descriptor->shader_register))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, descriptor->register_space))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_root_descriptor1(struct root_signature_writer_context *context,
const struct vkd3d_shader_root_descriptor1 *descriptor)
{
if (!write_dword(context, descriptor->shader_register))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, descriptor->register_space))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, descriptor->flags))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root descriptor.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_root_parameters(struct root_signature_writer_context *context,
@@ -2961,11 +3003,11 @@ static int shader_write_root_parameters(struct root_signature_writer_context *co
for (i = 0; i < parameter_count; ++i)
{
if (!write_dword(context, versioned_root_signature_get_parameter_type(desc, i)))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, versioned_root_signature_get_parameter_shader_visibility(desc, i)))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, 0xffffffff)) /* offset */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
}
for (i = 0; i < parameter_count; ++i)
@@ -2993,6 +3035,9 @@ static int shader_write_root_parameters(struct root_signature_writer_context *co
break;
default:
FIXME("Unrecognized type %#x.\n", versioned_root_signature_get_parameter_type(desc, i));
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE,
+ "Invalid/unrecognised root signature root parameter type %#x.",
+ versioned_root_signature_get_parameter_type(desc, i));
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@@ -3001,6 +3046,11 @@ static int shader_write_root_parameters(struct root_signature_writer_context *co
}
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature root parameters.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_static_samplers(struct root_signature_writer_context *context,
@@ -3012,34 +3062,39 @@ static int shader_write_static_samplers(struct root_signature_writer_context *co
for (i = 0; i < versioned_root_signature_get_static_sampler_count(desc); ++i)
{
if (!write_dword(context, samplers[i].filter))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].address_u))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].address_v))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].address_w))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_float(context, samplers[i].mip_lod_bias))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].max_anisotropy))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].comparison_func))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].border_colour))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_float(context, samplers[i].min_lod))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_float(context, samplers[i].max_lod))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].shader_register))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].register_space))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, samplers[i].shader_visibility))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
}
return VKD3D_OK;
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature static samplers.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
static int shader_write_root_signature(struct root_signature_writer_context *context,
@@ -3049,30 +3104,36 @@ static int shader_write_root_signature(struct root_signature_writer_context *con
int ret;
if (!write_dword(context, desc->version))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, versioned_root_signature_get_parameter_count(desc)))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, get_chunk_offset(context) + 4 * sizeof(DWORD))) /* offset */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, versioned_root_signature_get_static_sampler_count(desc)))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
samplers_offset_position = context->position;
if (!write_dword(context, 0xffffffff)) /* offset */
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if (!write_dword(context, versioned_root_signature_get_flags(desc)))
- return VKD3D_ERROR_OUT_OF_MEMORY;
+ goto fail;
if ((ret = shader_write_root_parameters(context, desc)) < 0)
return ret;
context->data[samplers_offset_position] = get_chunk_offset(context);
return shader_write_static_samplers(context, desc);
+
+fail:
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY,
+ "Out of memory while writing root signature.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
}
-static int validate_descriptor_table_v_1_0(const struct vkd3d_shader_root_descriptor_table *descriptor_table)
+static int validate_descriptor_table_v_1_0(const struct vkd3d_shader_root_descriptor_table *descriptor_table,
+ struct vkd3d_shader_message_context *message_context)
{
bool have_srv_uav_cbv = false;
bool have_sampler = false;
@@ -3095,6 +3156,8 @@ static int validate_descriptor_table_v_1_0(const struct vkd3d_shader_root_descri
else
{
WARN("Invalid descriptor range type %#x.\n", r->range_type);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE,
+ "Invalid root signature descriptor range type %#x.", r->range_type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
}
@@ -3102,13 +3165,16 @@ static int validate_descriptor_table_v_1_0(const struct vkd3d_shader_root_descri
if (have_srv_uav_cbv && have_sampler)
{
WARN("Samplers cannot be mixed with CBVs/SRVs/UAVs in descriptor tables.\n");
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES,
+ "Encountered both CBV/SRV/UAV and sampler descriptor ranges in the same root descriptor table.");
return VKD3D_ERROR_INVALID_ARGUMENT;
}
return VKD3D_OK;
}
-static int validate_descriptor_table_v_1_1(const struct vkd3d_shader_root_descriptor_table1 *descriptor_table)
+static int validate_descriptor_table_v_1_1(const struct vkd3d_shader_root_descriptor_table1 *descriptor_table,
+ struct vkd3d_shader_message_context *message_context)
{
bool have_srv_uav_cbv = false;
bool have_sampler = false;
@@ -3131,6 +3197,8 @@ static int validate_descriptor_table_v_1_1(const struct vkd3d_shader_root_descri
else
{
WARN("Invalid descriptor range type %#x.\n", r->range_type);
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE,
+ "Invalid root signature descriptor range type %#x.", r->range_type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
}
@@ -3138,13 +3206,16 @@ static int validate_descriptor_table_v_1_1(const struct vkd3d_shader_root_descri
if (have_srv_uav_cbv && have_sampler)
{
WARN("Samplers cannot be mixed with CBVs/SRVs/UAVs in descriptor tables.\n");
+ vkd3d_shader_error(message_context, VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES,
+ "Encountered both CBV/SRV/UAV and sampler descriptor ranges in the same root descriptor table.");
return VKD3D_ERROR_INVALID_ARGUMENT;
}
return VKD3D_OK;
}
-static int validate_root_signature_desc(const struct vkd3d_shader_versioned_root_signature_desc *desc)
+static int validate_root_signature_desc(const struct vkd3d_shader_versioned_root_signature_desc *desc,
+ struct vkd3d_shader_message_context *message_context)
{
int ret = VKD3D_OK;
unsigned int i;
@@ -3157,9 +3228,9 @@ static int validate_root_signature_desc(const struct vkd3d_shader_versioned_root
if (type == VKD3D_SHADER_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
{
if (desc->version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
- ret = validate_descriptor_table_v_1_0(&desc->u.v_1_0.parameters[i].u.descriptor_table);
+ ret = validate_descriptor_table_v_1_0(&desc->u.v_1_0.parameters[i].u.descriptor_table, message_context);
else
- ret = validate_descriptor_table_v_1_1(&desc->u.v_1_1.parameters[i].u.descriptor_table);
+ ret = validate_descriptor_table_v_1_1(&desc->u.v_1_1.parameters[i].u.descriptor_table, message_context);
}
if (ret < 0)
@@ -3170,37 +3241,46 @@ static int validate_root_signature_desc(const struct vkd3d_shader_versioned_root
}
int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_root_signature_desc *root_signature,
- struct vkd3d_shader_code *dxbc)
+ struct vkd3d_shader_code *dxbc, char **messages)
{
struct root_signature_writer_context context;
size_t total_size, chunk_size;
uint32_t checksum[4];
int ret;
- TRACE("root_signature %p, dxbc %p.\n", root_signature, dxbc);
+ TRACE("root_signature %p, dxbc %p, messages %p.\n", root_signature, dxbc, messages);
+
+ if (messages)
+ *messages = NULL;
+
+ memset(&context, 0, sizeof(context));
+ if (!vkd3d_shader_message_context_init(&context.message_context, VKD3D_SHADER_LOG_INFO, NULL))
+ return VKD3D_ERROR;
if (root_signature->version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0
&& root_signature->version != VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1)
{
+ ret = VKD3D_ERROR_INVALID_ARGUMENT;
WARN("Root signature version %#x not supported.\n", root_signature->version);
- return VKD3D_ERROR_INVALID_ARGUMENT;
+ vkd3d_shader_error(&context.message_context, VKD3D_SHADER_ERROR_RS_INVALID_VERSION,
+ "Root signature version %#x is not supported.", root_signature->version);
+ goto done;
}
- if ((ret = validate_root_signature_desc(root_signature)) < 0)
- return ret;
+ if ((ret = validate_root_signature_desc(root_signature, &context.message_context)) < 0)
+ goto done;
memset(dxbc, 0, sizeof(*dxbc));
- memset(&context, 0, sizeof(context));
if ((ret = shader_write_root_signature_header(&context)) < 0)
{
vkd3d_free(context.data);
- return ret;
+ goto done;
}
if ((ret = shader_write_root_signature(&context, root_signature)) < 0)
{
vkd3d_free(context.data);
- return ret;
+ goto done;
}
total_size = context.position * sizeof(DWORD);
@@ -3214,7 +3294,14 @@ int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_ro
vkd3d_compute_dxbc_checksum(dxbc->code, dxbc->size, checksum);
memcpy((uint32_t *)dxbc->code + 1, checksum, sizeof(checksum));
- return VKD3D_OK;
+ ret = VKD3D_OK;
+
+done:
+ vkd3d_shader_message_context_trace_messages(&context.message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&context.message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_message_context_cleanup(&context.message_context);
+ return ret;
}
static void free_descriptor_ranges(const struct vkd3d_shader_root_parameter *parameters, unsigned int count)
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 3161087..d728fdc 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -61,13 +61,20 @@
enum vkd3d_shader_error
{
- VKD3D_SHADER_ERROR_DXBC_INVALID_SIZE = 1,
- VKD3D_SHADER_ERROR_DXBC_INVALID_MAGIC = 2,
- VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM = 3,
- VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
- VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
- VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
- VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_SIZE = 1,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_MAGIC = 2,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM = 3,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
+ VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
+
+ VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
+
+ VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000,
+ VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001,
+ VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE = 3002,
+ VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE = 3003,
+ VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES = 3004,
};
enum VKD3D_SHADER_INSTRUCTION_HANDLER
diff --git a/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/vkd3d_main.c
index 3fd9c1b..327cdf8 100644
--- a/libs/vkd3d/vkd3d_main.c
+++ b/libs/vkd3d/vkd3d_main.c
@@ -543,6 +543,7 @@ HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
struct vkd3d_shader_versioned_root_signature_desc vkd3d_desc;
struct vkd3d_shader_code dxbc;
struct d3d_blob *blob_object;
+ char *messages;
HRESULT hr;
int ret;
@@ -565,13 +566,19 @@ HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
vkd3d_desc.version = VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0;
vkd3d_desc.u.v_1_0 = *(const struct vkd3d_shader_root_signature_desc *)desc;
- if ((ret = vkd3d_shader_serialize_root_signature(&vkd3d_desc, &dxbc)) < 0)
+ if ((ret = vkd3d_shader_serialize_root_signature(&vkd3d_desc, &dxbc, &messages)) < 0)
{
WARN("Failed to serialize root signature, vkd3d result %d.\n", ret);
- if (error_blob)
- FIXME("Ignoring error blob %p.\n", error_blob);
+ if (error_blob && messages)
+ {
+ if (FAILED(hr = d3d_blob_create(messages, strlen(messages), &blob_object)))
+ ERR("Failed to create error blob, hr %#x.\n", hr);
+ else
+ *error_blob = &blob_object->ID3DBlob_iface;
+ }
return hresult_from_vkd3d_result(ret);
}
+ vkd3d_shader_free_messages(messages);
if (FAILED(hr = d3d_blob_create((void *)dxbc.code, dxbc.size, &blob_object)))
{
@@ -591,6 +598,7 @@ HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGN
const struct vkd3d_shader_versioned_root_signature_desc *vkd3d_desc;
struct vkd3d_shader_code dxbc;
struct d3d_blob *blob_object;
+ char *messages;
HRESULT hr;
int ret;
@@ -606,13 +614,19 @@ HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGN
*error_blob = NULL;
vkd3d_desc = (const struct vkd3d_shader_versioned_root_signature_desc *)desc;
- if ((ret = vkd3d_shader_serialize_root_signature(vkd3d_desc, &dxbc)) < 0)
+ if ((ret = vkd3d_shader_serialize_root_signature(vkd3d_desc, &dxbc, &messages)) < 0)
{
WARN("Failed to serialize root signature, vkd3d result %d.\n", ret);
- if (error_blob)
- FIXME("Ignoring error blob %p.\n", error_blob);
+ if (error_blob && messages)
+ {
+ if (FAILED(hr = d3d_blob_create(messages, strlen(messages), &blob_object)))
+ ERR("Failed to create error blob, hr %#x.\n", hr);
+ else
+ *error_blob = &blob_object->ID3DBlob_iface;
+ }
return hresult_from_vkd3d_result(ret);
}
+ vkd3d_shader_free_messages(messages);
if (FAILED(hr = d3d_blob_create((void *)dxbc.code, dxbc.size, &blob_object)))
{
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c
index a730c86..e25dd20 100644
--- a/tests/vkd3d_shader_api.c
+++ b/tests/vkd3d_shader_api.c
@@ -127,7 +127,7 @@ static void test_vkd3d_shader_pfns(void)
pfn_vkd3d_shader_compile = vkd3d_shader_compile;
pfn_vkd3d_shader_scan = vkd3d_shader_scan;
- rc = pfn_vkd3d_shader_serialize_root_signature(&empty_rs_desc, &dxbc);
+ rc = pfn_vkd3d_shader_serialize_root_signature(&empty_rs_desc, &dxbc, NULL);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
rc = pfn_vkd3d_shader_parse_root_signature(&dxbc, &root_signature_desc, NULL);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
--
2.11.0
1
0
[PATCH vkd3d 4/5] vkd3d-shader: Report error messages from vkd3d_shader_parse_root_signature().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
include/vkd3d_shader.h | 4 ++--
libs/vkd3d-shader/dxbc.c | 13 ++++++++++---
libs/vkd3d-shader/vkd3d_shader_main.c | 6 ++----
libs/vkd3d-shader/vkd3d_shader_private.h | 5 +++++
libs/vkd3d/vkd3d_main.c | 4 ++--
tests/vkd3d_shader_api.c | 2 +-
6 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 0dd9829..8ee6724 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -753,7 +753,7 @@ void vkd3d_shader_free_messages(char *messages);
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_versioned_root_signature_desc *root_signature);
+ struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages);
void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signature_desc *root_signature);
/* FIXME: Add support for returning error messages (ID3DBlob). */
@@ -784,7 +784,7 @@ typedef void (*PFN_vkd3d_shader_free_messages)(char *messages);
typedef void (*PFN_vkd3d_shader_free_shader_code)(struct vkd3d_shader_code *code);
typedef int (*PFN_vkd3d_shader_parse_root_signature)(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_versioned_root_signature_desc *root_signature);
+ struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages);
typedef void (*PFN_vkd3d_shader_free_root_signature)(struct vkd3d_shader_versioned_root_signature_desc *root_signature);
typedef int (*PFN_vkd3d_shader_serialize_root_signature)(
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index a00dbe9..28159a9 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -2679,17 +2679,24 @@ static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *cont
}
int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_versioned_root_signature_desc *root_signature)
+ struct vkd3d_shader_versioned_root_signature_desc *root_signature, char **messages)
{
struct vkd3d_shader_message_context message_context;
int ret;
- TRACE("dxbc {%p, %zu}, root_signature %p.\n", dxbc->code, dxbc->size, root_signature);
+ TRACE("dxbc {%p, %zu}, root_signature %p, messages %p.\n", dxbc->code, dxbc->size, root_signature, messages);
memset(root_signature, 0, sizeof(*root_signature));
- if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_NONE, NULL))
+ if (messages)
+ *messages = NULL;
+ if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO, NULL))
return VKD3D_ERROR;
+
ret = parse_dxbc(dxbc->code, dxbc->size, &message_context, rts0_handler, root_signature);
+ vkd3d_shader_message_context_trace_messages(&message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+
vkd3d_shader_message_context_cleanup(&message_context);
if (ret < 0)
vkd3d_shader_free_root_signature(root_signature);
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 6511a89..0785c14 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -133,15 +133,13 @@ void vkd3d_shader_message_context_cleanup(struct vkd3d_shader_message_context *c
vkd3d_string_buffer_cleanup(&context->messages);
}
-#define vkd3d_shader_message_context_trace_messages(context) \
- vkd3d_shader_message_context_trace_messages_(context, __FUNCTION__)
-static void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context,
+void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context,
const char *function)
{
vkd3d_string_buffer_trace_(&context->messages, function);
}
-static char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context)
+char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context)
{
char *messages;
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 79056b3..3161087 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -830,8 +830,13 @@ struct vkd3d_shader_message_context
};
void vkd3d_shader_message_context_cleanup(struct vkd3d_shader_message_context *context) DECLSPEC_HIDDEN;
+char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context) DECLSPEC_HIDDEN;
bool vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context,
enum vkd3d_shader_log_level log_level, const char *source_name) DECLSPEC_HIDDEN;
+void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context,
+ const char *function) DECLSPEC_HIDDEN;
+#define vkd3d_shader_message_context_trace_messages(context) \
+ vkd3d_shader_message_context_trace_messages_(context, __FUNCTION__)
void vkd3d_shader_error(struct vkd3d_shader_message_context *context, enum vkd3d_shader_error error,
const char *format, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
diff --git a/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/vkd3d_main.c
index 5d7c71e..3fd9c1b 100644
--- a/libs/vkd3d/vkd3d_main.c
+++ b/libs/vkd3d/vkd3d_main.c
@@ -174,7 +174,7 @@ int vkd3d_parse_root_signature_v_1_0(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_versioned_root_signature_desc desc, converted_desc;
int ret;
- if ((ret = vkd3d_shader_parse_root_signature(dxbc, &desc)) < 0)
+ if ((ret = vkd3d_shader_parse_root_signature(dxbc, &desc, NULL)) < 0)
{
WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
return ret;
@@ -389,7 +389,7 @@ static HRESULT d3d12_versioned_root_signature_deserializer_init(struct d3d12_ver
deserializer->ID3D12VersionedRootSignatureDeserializer_iface.lpVtbl = &d3d12_versioned_root_signature_deserializer_vtbl;
deserializer->refcount = 1;
- if ((ret = vkd3d_shader_parse_root_signature(dxbc, &deserializer->desc.vkd3d)) < 0)
+ if ((ret = vkd3d_shader_parse_root_signature(dxbc, &deserializer->desc.vkd3d, NULL)) < 0)
{
WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
return hresult_from_vkd3d_result(ret);
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c
index 6977945..a730c86 100644
--- a/tests/vkd3d_shader_api.c
+++ b/tests/vkd3d_shader_api.c
@@ -129,7 +129,7 @@ static void test_vkd3d_shader_pfns(void)
rc = pfn_vkd3d_shader_serialize_root_signature(&empty_rs_desc, &dxbc);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
- rc = pfn_vkd3d_shader_parse_root_signature(&dxbc, &root_signature_desc);
+ rc = pfn_vkd3d_shader_parse_root_signature(&dxbc, &root_signature_desc, NULL);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
pfn_vkd3d_shader_free_root_signature(&root_signature_desc);
pfn_vkd3d_shader_free_shader_code(&dxbc);
--
2.11.0
1
0
[PATCH vkd3d 3/5] vkd3d-shader: Report error messages from vkd3d_shader_parse_input_signature().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
include/vkd3d_shader.h | 4 ++--
libs/vkd3d-shader/dxbc.c | 8 ++------
libs/vkd3d-shader/vkd3d_shader_main.c | 21 ++++++++++++++++++---
libs/vkd3d-shader/vkd3d_shader_private.h | 2 +-
libs/vkd3d/state.c | 2 +-
tests/vkd3d_shader_api.c | 2 +-
6 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 96d0545..0dd9829 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -767,7 +767,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
void vkd3d_shader_free_scan_descriptor_info(struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info);
int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_signature *signature);
+ struct vkd3d_shader_signature *signature, char **messages);
struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element(
const struct vkd3d_shader_signature *signature, const char *semantic_name,
unsigned int semantic_index, unsigned int stream_index);
@@ -798,7 +798,7 @@ typedef void (*PFN_vkd3d_shader_free_scan_descriptor_info)(
struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info);
typedef int (*PFN_vkd3d_shader_parse_input_signature)(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_signature *signature);
+ struct vkd3d_shader_signature *signature, char **messages);
typedef struct vkd3d_shader_signature_element * (*PFN_vkd3d_shader_find_signature_element)(
const struct vkd3d_shader_signature *signature, const char *semantic_name,
unsigned int semantic_index, unsigned int stream_index);
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index f738abe..a00dbe9 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -2132,17 +2132,13 @@ static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
}
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
- struct vkd3d_shader_signature *signature)
+ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature)
{
- struct vkd3d_shader_message_context message_context;
int ret;
memset(signature, 0, sizeof(*signature));
- if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_NONE, NULL))
- return VKD3D_ERROR;
- if ((ret = parse_dxbc(dxbc, dxbc_length, &message_context, isgn_handler, signature)) < 0)
+ if ((ret = parse_dxbc(dxbc, dxbc_length, message_context, isgn_handler, signature)) < 0)
ERR("Failed to parse input signature.\n");
- vkd3d_shader_message_context_cleanup(&message_context);
return ret;
}
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 5d50487..6511a89 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -971,11 +971,26 @@ void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signatu
}
int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_signature *signature)
+ struct vkd3d_shader_signature *signature, char **messages)
{
- TRACE("dxbc {%p, %zu}, signature %p.\n", dxbc->code, dxbc->size, signature);
+ struct vkd3d_shader_message_context message_context;
+ int ret;
+
+ TRACE("dxbc {%p, %zu}, signature %p, messages %p.\n", dxbc->code, dxbc->size, signature, messages);
+
+ if (messages)
+ *messages = NULL;
+ if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO, NULL))
+ return VKD3D_ERROR;
- return shader_parse_input_signature(dxbc->code, dxbc->size, signature);
+ ret = shader_parse_input_signature(dxbc->code, dxbc->size, &message_context, signature);
+ vkd3d_shader_message_context_trace_messages(&message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+
+ vkd3d_shader_message_context_cleanup(&message_context);
+
+ return ret;
}
struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element(
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index ae2f6c2..79056b3 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -840,7 +840,7 @@ int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
void free_shader_desc(struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
- struct vkd3d_shader_signature *signature) DECLSPEC_HIDDEN;
+ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature) DECLSPEC_HIDDEN;
struct vkd3d_dxbc_compiler;
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index 93f22ce..449f242 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -2316,7 +2316,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
switch (shader_stages[i].stage)
{
case VK_SHADER_STAGE_VERTEX_BIT:
- if ((ret = vkd3d_shader_parse_input_signature(&dxbc, &input_signature)) < 0)
+ if ((ret = vkd3d_shader_parse_input_signature(&dxbc, &input_signature, NULL)) < 0)
{
hr = hresult_from_vkd3d_result(ret);
goto fail;
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c
index be63b39..6977945 100644
--- a/tests/vkd3d_shader_api.c
+++ b/tests/vkd3d_shader_api.c
@@ -134,7 +134,7 @@ static void test_vkd3d_shader_pfns(void)
pfn_vkd3d_shader_free_root_signature(&root_signature_desc);
pfn_vkd3d_shader_free_shader_code(&dxbc);
- rc = pfn_vkd3d_shader_parse_input_signature(&vs, &signature);
+ rc = pfn_vkd3d_shader_parse_input_signature(&vs, &signature, NULL);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
element = pfn_vkd3d_shader_find_signature_element(&signature, "position", 0, 0);
ok(element, "Could not find shader signature element.\n");
--
2.11.0
1
0
[PATCH vkd3d 2/5] vkd3d-shader: Pass a vkd3d_shader_compile_info structure to vkd3d_shader_scan_dxbc().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
In order to allow it to handle different source types.
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
include/vkd3d_shader.h | 18 +++---
libs/vkd3d-shader/spirv.c | 33 ++---------
libs/vkd3d-shader/vkd3d_shader.map | 4 +-
libs/vkd3d-shader/vkd3d_shader_main.c | 97 +++++++++++++++++++-------------
libs/vkd3d-shader/vkd3d_shader_private.h | 23 +++++++-
libs/vkd3d/state.c | 41 ++++++++++----
tests/vkd3d_shader_api.c | 20 +++++--
7 files changed, 141 insertions(+), 95 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 69a98e0..96d0545 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -32,7 +32,7 @@ enum vkd3d_shader_structure_type
/* 1.2 */
VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO,
- VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO,
+ VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_DOMAIN_SHADER_TARGET_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO,
@@ -653,10 +653,11 @@ struct vkd3d_shader_descriptor_info
unsigned int count;
};
-struct vkd3d_shader_scan_info
+/* Extends vkd3d_shader_compile_info. */
+struct vkd3d_shader_scan_descriptor_info
{
enum vkd3d_shader_structure_type type;
- void *next;
+ const void *next;
struct vkd3d_shader_descriptor_info *descriptors;
unsigned int descriptor_count;
@@ -762,9 +763,8 @@ int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_ro
int vkd3d_shader_convert_root_signature(struct vkd3d_shader_versioned_root_signature_desc *dst,
enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src);
-int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_scan_info *scan_info, char **messages);
-void vkd3d_shader_free_scan_info(struct vkd3d_shader_scan_info *scan_info);
+int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages);
+void vkd3d_shader_free_scan_descriptor_info(struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info);
int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature);
@@ -793,9 +793,9 @@ typedef int (*PFN_vkd3d_shader_serialize_root_signature)(
typedef int (*PFN_vkd3d_shader_convert_root_signature)(struct vkd3d_shader_versioned_root_signature_desc *dst,
enum vkd3d_shader_root_signature_version version, const struct vkd3d_shader_versioned_root_signature_desc *src);
-typedef int (*PFN_vkd3d_shader_scan_dxbc)(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_scan_info *scan_info, char **messages);
-typedef void (*PFN_vkd3d_shader_free_scan_info)(struct vkd3d_shader_scan_info *scan_info);
+typedef int (*PFN_vkd3d_shader_scan)(const struct vkd3d_shader_compile_info *compile_info, char **messages);
+typedef void (*PFN_vkd3d_shader_free_scan_descriptor_info)(
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info);
typedef int (*PFN_vkd3d_shader_parse_input_signature)(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature);
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 3ece044..86ee263 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -111,27 +111,6 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
#endif /* HAVE_SPIRV_TOOLS */
-struct vkd3d_struct
-{
- enum vkd3d_shader_structure_type type;
- const void *next;
-};
-
-#define vkd3d_find_struct(c, t) vkd3d_find_struct_(c, VKD3D_SHADER_STRUCTURE_TYPE_##t)
-static const void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
- enum vkd3d_shader_structure_type type)
-{
- while (chain)
- {
- if (chain->type == type)
- return chain;
-
- chain = chain->next;
- }
-
- return NULL;
-}
-
static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
unsigned int index)
{
@@ -2103,7 +2082,7 @@ struct vkd3d_dxbc_compiler
uint32_t binding_idx;
- const struct vkd3d_shader_scan_info *scan_info;
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
unsigned int input_control_point_count;
unsigned int output_control_point_count;
bool use_vocp;
@@ -2134,7 +2113,7 @@ static const char *vkd3d_dxbc_compiler_get_entry_point_name(const struct vkd3d_d
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
- const struct vkd3d_shader_scan_info *scan_info)
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info)
{
const struct vkd3d_shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature;
@@ -2216,7 +2195,7 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
}
}
- compiler->scan_info = scan_info;
+ compiler->scan_descriptor_info = scan_descriptor_info;
vkd3d_dxbc_compiler_emit_initial_declarations(compiler);
@@ -5177,13 +5156,13 @@ static const struct vkd3d_shader_descriptor_info *vkd3d_dxbc_compiler_get_descri
struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_descriptor_type type,
unsigned int register_space, unsigned int register_index)
{
- const struct vkd3d_shader_scan_info *scan_info = compiler->scan_info;
+ const struct vkd3d_shader_scan_descriptor_info *descriptor_info = compiler->scan_descriptor_info;
const struct vkd3d_shader_descriptor_info *d;
unsigned int i;
- for (i = 0; i < scan_info->descriptor_count; ++i)
+ for (i = 0; i < descriptor_info->descriptor_count; ++i)
{
- d = &scan_info->descriptors[i];
+ d = &descriptor_info->descriptors[i];
if (d->type == type && d->register_space == register_space && d->register_index == register_index)
return d;
}
diff --git a/libs/vkd3d-shader/vkd3d_shader.map b/libs/vkd3d-shader/vkd3d_shader.map
index 55b50ad..9c9f0a5 100644
--- a/libs/vkd3d-shader/vkd3d_shader.map
+++ b/libs/vkd3d-shader/vkd3d_shader.map
@@ -6,12 +6,12 @@ global:
vkd3d_shader_find_signature_element;
vkd3d_shader_free_messages;
vkd3d_shader_free_root_signature;
- vkd3d_shader_free_scan_info;
+ vkd3d_shader_free_scan_descriptor_info;
vkd3d_shader_free_shader_code;
vkd3d_shader_free_shader_signature;
vkd3d_shader_parse_input_signature;
vkd3d_shader_parse_root_signature;
- vkd3d_shader_scan_dxbc;
+ vkd3d_shader_scan;
vkd3d_shader_serialize_root_signature;
local: *;
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index cf8b289..5d50487 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -285,10 +285,11 @@ void vkd3d_shader_free_messages(char *messages)
int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, char **messages)
{
+ struct vkd3d_shader_scan_descriptor_info scan_descriptor_info;
struct vkd3d_shader_message_context message_context;
struct vkd3d_shader_instruction instruction;
+ struct vkd3d_shader_compile_info scan_info;
struct vkd3d_dxbc_compiler *spirv_compiler;
- struct vkd3d_shader_scan_info scan_info;
struct vkd3d_shader_parser parser;
int ret;
@@ -300,9 +301,12 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
if ((ret = vkd3d_shader_validate_compile_info(compile_info)) < 0)
return ret;
- scan_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO;
- scan_info.next = NULL;
- if ((ret = vkd3d_shader_scan_dxbc(&compile_info->source, &scan_info, messages)) < 0)
+ scan_info = *compile_info;
+ scan_descriptor_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO;
+ scan_descriptor_info.next = scan_info.next;
+ scan_info.next = &scan_descriptor_info;
+
+ if ((ret = vkd3d_shader_scan(&scan_info, messages)) < 0)
return ret;
if (!vkd3d_shader_message_context_init(&message_context, compile_info->log_level, compile_info->source_name))
@@ -317,15 +321,19 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
}
vkd3d_shader_message_context_cleanup(&message_context);
if (ret < 0)
+ {
+ vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
return ret;
+ }
vkd3d_shader_dump_shader(parser.shader_version.type, &compile_info->source);
if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version,
- &parser.shader_desc, compile_info, &scan_info)))
+ &parser.shader_desc, compile_info, &scan_descriptor_info)))
{
ERR("Failed to create DXBC compiler.\n");
vkd3d_shader_parser_destroy(&parser);
+ vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
return VKD3D_ERROR;
}
@@ -336,9 +344,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
if (instruction.handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
- vkd3d_dxbc_compiler_destroy(spirv_compiler);
- vkd3d_shader_parser_destroy(&parser);
- return VKD3D_ERROR_INVALID_ARGUMENT;
+ ret = VKD3D_ERROR_INVALID_SHADER;
+ break;
}
if ((ret = vkd3d_dxbc_compiler_handle_instruction(spirv_compiler, &instruction)) < 0)
@@ -350,13 +357,13 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
vkd3d_dxbc_compiler_destroy(spirv_compiler);
vkd3d_shader_parser_destroy(&parser);
- vkd3d_shader_free_scan_info(&scan_info);
+ vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
return ret;
}
struct vkd3d_shader_scan_context
{
- struct vkd3d_shader_scan_info *scan_info;
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
size_t descriptors_size;
struct vkd3d_shader_message_context message_context;
@@ -385,11 +392,12 @@ struct vkd3d_shader_scan_context
};
static bool vkd3d_shader_scan_context_init(struct vkd3d_shader_scan_context *context,
- struct vkd3d_shader_scan_info *scan_info)
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
+ enum vkd3d_shader_log_level log_level, const char *source_name)
{
memset(context, 0, sizeof(*context));
- context->scan_info = scan_info;
- return vkd3d_shader_message_context_init(&context->message_context, VKD3D_SHADER_LOG_INFO, NULL);
+ context->scan_descriptor_info = scan_descriptor_info;
+ return vkd3d_shader_message_context_init(&context->message_context, log_level, source_name);
}
static void vkd3d_shader_scan_context_cleanup(struct vkd3d_shader_scan_context *context)
@@ -471,7 +479,7 @@ static struct vkd3d_shader_descriptor_info *vkd3d_shader_scan_get_uav_descriptor
for (i = 0; i < context->uav_range_count; ++i)
{
if (context->uav_ranges[i].id == range_id)
- return &context->scan_info->descriptors[context->uav_ranges[i].descriptor_idx];
+ return &context->scan_descriptor_info->descriptors[context->uav_ranges[i].descriptor_idx];
}
return NULL;
@@ -492,7 +500,7 @@ static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_context *
{
struct vkd3d_shader_descriptor_info *d;
- if (!context->scan_info)
+ if (!context->scan_descriptor_info)
return;
d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset);
@@ -511,7 +519,7 @@ static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_contex
{
struct vkd3d_shader_descriptor_info *d;
- if (!context->scan_info)
+ if (!context->scan_descriptor_info)
return;
d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset);
@@ -523,17 +531,17 @@ static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *c
enum vkd3d_shader_resource_type resource_type, enum vkd3d_shader_resource_data_type resource_data_type,
unsigned int flags)
{
- struct vkd3d_shader_scan_info *scan_info = context->scan_info;
+ struct vkd3d_shader_scan_descriptor_info *info = context->scan_descriptor_info;
struct vkd3d_shader_descriptor_info *d;
- if (!vkd3d_array_reserve((void **)&scan_info->descriptors, &context->descriptors_size,
- scan_info->descriptor_count + 1, sizeof(*scan_info->descriptors)))
+ if (!vkd3d_array_reserve((void **)&info->descriptors, &context->descriptors_size,
+ info->descriptor_count + 1, sizeof(*info->descriptors)))
{
ERR("Failed to allocate descriptor info.\n");
return false;
}
- d = &scan_info->descriptors[scan_info->descriptor_count];
+ d = &info->descriptors[info->descriptor_count];
d->type = type;
d->register_space = register_space;
d->register_index = register_index;
@@ -541,7 +549,7 @@ static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *c
d->resource_data_type = resource_data_type;
d->flags = flags;
d->count = 1;
- ++scan_info->descriptor_count;
+ ++info->descriptor_count;
return true;
}
@@ -568,7 +576,7 @@ static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_sc
{
const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb;
- if (!context->scan_info)
+ if (!context->scan_descriptor_info)
return;
vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, cb->register_space,
@@ -581,7 +589,7 @@ static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_conte
const struct vkd3d_shader_sampler *sampler = &instruction->declaration.sampler;
unsigned int flags;
- if (!context->scan_info)
+ if (!context->scan_descriptor_info)
return;
if (instruction->flags & VKD3DSI_SAMPLER_COMPARISON_MODE)
@@ -598,7 +606,7 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont
{
enum vkd3d_shader_descriptor_type type;
- if (!context->scan_info)
+ if (!context->scan_descriptor_info)
return;
if (resource->reg.reg.type == VKD3DSPR_UAV)
@@ -609,7 +617,7 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont
resource->register_index, resource_type, resource_data_type, 0);
if (type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV)
vkd3d_shader_scan_add_uav_range(context, resource->reg.reg.idx[0].offset,
- context->scan_info->descriptor_count - 1);
+ context->scan_descriptor_info->descriptor_count - 1);
}
static void vkd3d_shader_scan_typed_resource_declaration(struct vkd3d_shader_scan_context *context,
@@ -811,31 +819,44 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte
return VKD3D_OK;
}
-int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
- struct vkd3d_shader_scan_info *scan_info, char **messages)
+int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages)
{
+ struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
struct vkd3d_shader_message_context *message_context;
struct vkd3d_shader_instruction instruction;
struct vkd3d_shader_scan_context context;
struct vkd3d_shader_parser parser;
int ret;
- TRACE("dxbc {%p, %zu}, scan_info %p, messages %p.\n", dxbc->code, dxbc->size, scan_info, messages);
+ TRACE("compile_info %p, messages %p.\n", compile_info, messages);
if (messages)
*messages = NULL;
- if (scan_info->type != VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO)
+ if (compile_info->type != VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO)
{
- WARN("Invalid structure type %#x.\n", scan_info->type);
+ WARN("Invalid structure type %#x.\n", compile_info->type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
- if (!vkd3d_shader_scan_context_init(&context, scan_info))
+ if (compile_info->source_type != VKD3D_SHADER_SOURCE_DXBC_TPF)
+ {
+ WARN("Unsupported source type %#x.\n", compile_info->source_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+
+ if ((scan_descriptor_info = vkd3d_find_struct(compile_info->next, SCAN_DESCRIPTOR_INFO)))
+ {
+ scan_descriptor_info->descriptors = NULL;
+ scan_descriptor_info->descriptor_count = 0;
+ }
+
+ if (!vkd3d_shader_scan_context_init(&context, scan_descriptor_info,
+ compile_info->log_level, compile_info->source_name))
return VKD3D_ERROR;
message_context = &context.message_context;
- if ((ret = vkd3d_shader_parser_init(&parser, dxbc, message_context)) < 0)
+ if ((ret = vkd3d_shader_parser_init(&parser, &compile_info->source, message_context)) < 0)
{
vkd3d_shader_message_context_trace_messages(message_context);
if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(message_context)))
@@ -847,8 +868,6 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
if (TRACE_ON())
vkd3d_shader_trace(parser.data);
- memset(scan_info, 0, sizeof(*scan_info));
-
message_context->line = 2; /* Line 1 is the version token. */
message_context->column = 1;
while (!shader_sm4_is_end(parser.data, &parser.ptr))
@@ -858,14 +877,14 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
if (instruction.handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
- vkd3d_shader_free_scan_info(scan_info);
+ vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info);
ret = VKD3D_ERROR_INVALID_SHADER;
goto done;
}
if ((ret = vkd3d_shader_scan_instruction(&context, &instruction)) < 0)
{
- vkd3d_shader_free_scan_info(scan_info);
+ vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info);
goto done;
}
++message_context->line;
@@ -882,12 +901,12 @@ done:
return ret;
}
-void vkd3d_shader_free_scan_info(struct vkd3d_shader_scan_info *scan_info)
+void vkd3d_shader_free_scan_descriptor_info(struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info)
{
- if (!scan_info)
+ if (!scan_descriptor_info)
return;
- vkd3d_free(scan_info->descriptors);
+ vkd3d_free(scan_descriptor_info->descriptors);
}
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code)
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 4fa17d6..ae2f6c2 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -846,7 +846,7 @@ struct vkd3d_dxbc_compiler;
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
- const struct vkd3d_shader_scan_info *scan_info) DECLSPEC_HIDDEN;
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info) DECLSPEC_HIDDEN;
int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN;
int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
@@ -941,6 +941,27 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned
return compacted_swizzle;
}
+struct vkd3d_struct
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+};
+
+#define vkd3d_find_struct(c, t) vkd3d_find_struct_(c, VKD3D_SHADER_STRUCTURE_TYPE_##t)
+static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
+ enum vkd3d_shader_structure_type type)
+{
+ while (chain)
+ {
+ if (chain->type == type)
+ return (void *)chain;
+
+ chain = chain->next;
+ }
+
+ return NULL;
+}
+
#define VKD3D_DXBC_MAX_SOURCE_COUNT 6
#define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t))
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index 316132b..93f22ce 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -1376,6 +1376,25 @@ static HRESULT create_shader_stage(struct d3d12_device *device,
return S_OK;
}
+static int vkd3d_scan_dxbc(const D3D12_SHADER_BYTECODE *code,
+ struct vkd3d_shader_scan_descriptor_info *descriptor_info)
+{
+ struct vkd3d_shader_compile_info compile_info;
+
+ compile_info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
+ compile_info.next = descriptor_info;
+ compile_info.source.code = code->pShaderBytecode;
+ compile_info.source.size = code->BytecodeLength;
+ compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
+ compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY;
+ compile_info.options = NULL;
+ compile_info.option_count = 0;
+ compile_info.log_level = VKD3D_SHADER_LOG_NONE;
+ compile_info.source_name = NULL;
+
+ return vkd3d_shader_scan(&compile_info, NULL);
+}
+
static HRESULT vkd3d_create_compute_pipeline(struct d3d12_device *device,
const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface,
VkPipelineLayout vk_pipeline_layout, VkPipeline *vk_pipeline)
@@ -1409,7 +1428,7 @@ static HRESULT vkd3d_create_compute_pipeline(struct d3d12_device *device,
static HRESULT d3d12_pipeline_state_init_compute_uav_counters(struct d3d12_pipeline_state *state,
struct d3d12_device *device, const struct d3d12_root_signature *root_signature,
- const struct vkd3d_shader_scan_info *shader_info)
+ const struct vkd3d_shader_scan_descriptor_info *shader_info)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_descriptor_set_context context;
@@ -1503,11 +1522,10 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ struct vkd3d_shader_scan_descriptor_info shader_info;
struct vkd3d_shader_interface_info shader_interface;
const struct d3d12_root_signature *root_signature;
- struct vkd3d_shader_scan_info shader_info;
VkPipelineLayout vk_pipeline_layout;
- struct vkd3d_shader_code dxbc;
HRESULT hr;
int ret;
@@ -1525,11 +1543,9 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
return E_INVALIDARG;
}
- dxbc.code = desc->CS.pShaderBytecode;
- dxbc.size = desc->CS.BytecodeLength;
- shader_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO;
+ shader_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO;
shader_info.next = NULL;
- if ((ret = vkd3d_shader_scan_dxbc(&dxbc, &shader_info, NULL)) < 0)
+ if ((ret = vkd3d_scan_dxbc(&desc->CS, &shader_info)) < 0)
{
WARN("Failed to scan shader bytecode, vkd3d result %d.\n", ret);
return hresult_from_vkd3d_result(ret);
@@ -1541,7 +1557,7 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
WARN("Failed to create descriptor set layout for UAV counters, hr %#x.\n", hr);
return hr;
}
- vkd3d_shader_free_scan_info(&shader_info);
+ vkd3d_shader_free_scan_descriptor_info(&shader_info);
shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
shader_interface.next = NULL;
@@ -2266,14 +2282,17 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
for (i = 0; i < ARRAY_SIZE(shader_stages); ++i)
{
+ struct vkd3d_shader_scan_descriptor_info shader_info =
+ {
+ .type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO,
+ };
const D3D12_SHADER_BYTECODE *b = (const void *)((uintptr_t)desc + shader_stages[i].offset);
- struct vkd3d_shader_scan_info shader_info = {VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO};
const struct vkd3d_shader_code dxbc = {b->pShaderBytecode, b->BytecodeLength};
if (!b->pShaderBytecode)
continue;
- if ((ret = vkd3d_shader_scan_dxbc(&dxbc, &shader_info, NULL)) < 0)
+ if ((ret = vkd3d_scan_dxbc(b, &shader_info)) < 0)
{
WARN("Failed to scan shader bytecode, stage %#x, vkd3d result %d.\n",
shader_stages[i].stage, ret);
@@ -2291,7 +2310,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
break;
}
}
- vkd3d_shader_free_scan_info(&shader_info);
+ vkd3d_shader_free_scan_descriptor_info(&shader_info);
target_info = NULL;
switch (shader_stages[i].stage)
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c
index 079559a..be63b39 100644
--- a/tests/vkd3d_shader_api.c
+++ b/tests/vkd3d_shader_api.c
@@ -68,10 +68,14 @@ static void test_invalid_shaders(void)
rc = vkd3d_shader_compile(&info, &spirv, NULL);
ok(rc == VKD3D_ERROR_INVALID_SHADER, "Got unexpected error code %d.\n", rc);
+
+ rc = vkd3d_shader_scan(&info, NULL);
+ ok(rc == VKD3D_ERROR_INVALID_SHADER, "Got unexpected error code %d.\n", rc);
}
static void test_vkd3d_shader_pfns(void)
{
+ PFN_vkd3d_shader_free_scan_descriptor_info pfn_vkd3d_shader_free_scan_descriptor_info;
PFN_vkd3d_shader_serialize_root_signature pfn_vkd3d_shader_serialize_root_signature;
PFN_vkd3d_shader_find_signature_element pfn_vkd3d_shader_find_signature_element;
PFN_vkd3d_shader_free_shader_signature pfn_vkd3d_shader_free_shader_signature;
@@ -79,13 +83,13 @@ static void test_vkd3d_shader_pfns(void)
PFN_vkd3d_shader_parse_root_signature pfn_vkd3d_shader_parse_root_signature;
PFN_vkd3d_shader_free_root_signature pfn_vkd3d_shader_free_root_signature;
PFN_vkd3d_shader_free_shader_code pfn_vkd3d_shader_free_shader_code;
- PFN_vkd3d_shader_scan_dxbc pfn_vkd3d_shader_scan_dxbc;
PFN_vkd3d_shader_compile pfn_vkd3d_shader_compile;
+ PFN_vkd3d_shader_scan pfn_vkd3d_shader_scan;
struct vkd3d_shader_versioned_root_signature_desc root_signature_desc;
+ struct vkd3d_shader_scan_descriptor_info descriptor_info;
struct vkd3d_shader_signature_element *element;
struct vkd3d_shader_compile_info compile_info;
- struct vkd3d_shader_scan_info scan_info;
struct vkd3d_shader_signature signature;
struct vkd3d_shader_code dxbc, spirv;
int rc;
@@ -112,6 +116,7 @@ static void test_vkd3d_shader_pfns(void)
};
static const struct vkd3d_shader_code vs = {vs_code, sizeof(vs_code)};
+ pfn_vkd3d_shader_free_scan_descriptor_info = vkd3d_shader_free_scan_descriptor_info;
pfn_vkd3d_shader_serialize_root_signature = vkd3d_shader_serialize_root_signature;
pfn_vkd3d_shader_find_signature_element = vkd3d_shader_find_signature_element;
pfn_vkd3d_shader_free_shader_signature = vkd3d_shader_free_shader_signature;
@@ -119,8 +124,8 @@ static void test_vkd3d_shader_pfns(void)
pfn_vkd3d_shader_parse_root_signature = vkd3d_shader_parse_root_signature;
pfn_vkd3d_shader_free_root_signature = vkd3d_shader_free_root_signature;
pfn_vkd3d_shader_free_shader_code = vkd3d_shader_free_shader_code;
- pfn_vkd3d_shader_scan_dxbc = vkd3d_shader_scan_dxbc;
pfn_vkd3d_shader_compile = vkd3d_shader_compile;
+ pfn_vkd3d_shader_scan = vkd3d_shader_scan;
rc = pfn_vkd3d_shader_serialize_root_signature(&empty_rs_desc, &dxbc);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
@@ -149,10 +154,13 @@ static void test_vkd3d_shader_pfns(void)
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
pfn_vkd3d_shader_free_shader_code(&spirv);
- memset(&scan_info, 0, sizeof(scan_info));
- scan_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO;
- rc = pfn_vkd3d_shader_scan_dxbc(&vs, &scan_info, NULL);
+ memset(&descriptor_info, 0, sizeof(descriptor_info));
+ descriptor_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO;
+ compile_info.next = &descriptor_info;
+
+ rc = pfn_vkd3d_shader_scan(&compile_info, NULL);
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
+ pfn_vkd3d_shader_free_scan_descriptor_info(&descriptor_info);
}
START_TEST(vkd3d_shader_api)
--
2.11.0
1
0
[PATCH vkd3d 1/5] vkd3d-shader: Validate control flow instructions in vkd3d_shader_scan_dxbc().
by Henri Verbeet July 30, 2020
by Henri Verbeet July 30, 2020
July 30, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
libs/vkd3d-shader/vkd3d_shader_main.c | 276 +++++++++++++++++++++++++++++--
libs/vkd3d-shader/vkd3d_shader_private.h | 1 +
2 files changed, 259 insertions(+), 18 deletions(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 5597992..cf8b289 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -359,6 +359,22 @@ struct vkd3d_shader_scan_context
struct vkd3d_shader_scan_info *scan_info;
size_t descriptors_size;
+ struct vkd3d_shader_message_context message_context;
+
+ struct vkd3d_shader_cf_info
+ {
+ enum
+ {
+ VKD3D_SHADER_BLOCK_IF,
+ VKD3D_SHADER_BLOCK_LOOP,
+ VKD3D_SHADER_BLOCK_SWITCH,
+ } type;
+ bool inside_block;
+ bool has_default;
+ } *cf_info;
+ size_t cf_info_size;
+ size_t cf_info_count;
+
struct
{
unsigned int id;
@@ -368,6 +384,85 @@ struct vkd3d_shader_scan_context
size_t uav_range_count;
};
+static bool vkd3d_shader_scan_context_init(struct vkd3d_shader_scan_context *context,
+ struct vkd3d_shader_scan_info *scan_info)
+{
+ memset(context, 0, sizeof(*context));
+ context->scan_info = scan_info;
+ return vkd3d_shader_message_context_init(&context->message_context, VKD3D_SHADER_LOG_INFO, NULL);
+}
+
+static void vkd3d_shader_scan_context_cleanup(struct vkd3d_shader_scan_context *context)
+{
+ vkd3d_free(context->uav_ranges);
+ vkd3d_free(context->cf_info);
+ vkd3d_shader_message_context_cleanup(&context->message_context);
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_get_current_cf_info(struct vkd3d_shader_scan_context *context)
+{
+ if (!context->cf_info_count)
+ return NULL;
+ return &context->cf_info[context->cf_info_count - 1];
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_push_cf_info(struct vkd3d_shader_scan_context *context)
+{
+ struct vkd3d_shader_cf_info *cf_info;
+
+ if (!vkd3d_array_reserve((void **)&context->cf_info, &context->cf_info_size,
+ context->cf_info_count + 1, sizeof(*context->cf_info)))
+ {
+ ERR("Failed to allocate UAV range.\n");
+ return false;
+ }
+
+ cf_info = &context->cf_info[context->cf_info_count++];
+ memset(cf_info, 0, sizeof(*cf_info));
+
+ return cf_info;
+}
+
+static void vkd3d_shader_scan_pop_cf_info(struct vkd3d_shader_scan_context *context)
+{
+ assert(context->cf_info_count);
+
+ --context->cf_info_count;
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_find_innermost_breakable_cf_info(
+ struct vkd3d_shader_scan_context *context)
+{
+ size_t count = context->cf_info_count;
+ struct vkd3d_shader_cf_info *cf_info;
+
+ while (count)
+ {
+ cf_info = &context->cf_info[--count];
+ if (cf_info->type == VKD3D_SHADER_BLOCK_LOOP
+ || cf_info->type == VKD3D_SHADER_BLOCK_SWITCH)
+ return cf_info;
+ }
+
+ return NULL;
+}
+
+static struct vkd3d_shader_cf_info *vkd3d_shader_scan_find_innermost_loop_cf_info(
+ struct vkd3d_shader_scan_context *context)
+{
+ size_t count = context->cf_info_count;
+ struct vkd3d_shader_cf_info *cf_info;
+
+ while (count)
+ {
+ cf_info = &context->cf_info[--count];
+ if (cf_info->type == VKD3D_SHADER_BLOCK_LOOP)
+ return cf_info;
+ }
+
+ return NULL;
+}
+
static struct vkd3d_shader_descriptor_info *vkd3d_shader_scan_get_uav_descriptor_info(
const struct vkd3d_shader_scan_context *context, unsigned int range_id)
{
@@ -397,6 +492,9 @@ static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_context *
{
struct vkd3d_shader_descriptor_info *d;
+ if (!context->scan_info)
+ return;
+
d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset);
d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ;
}
@@ -413,6 +511,9 @@ static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_contex
{
struct vkd3d_shader_descriptor_info *d;
+ if (!context->scan_info)
+ return;
+
d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset);
d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER;
}
@@ -467,6 +568,9 @@ static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_sc
{
const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb;
+ if (!context->scan_info)
+ return;
+
vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, cb->register_space,
cb->register_index, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0);
}
@@ -477,6 +581,9 @@ static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_conte
const struct vkd3d_shader_sampler *sampler = &instruction->declaration.sampler;
unsigned int flags;
+ if (!context->scan_info)
+ return;
+
if (instruction->flags & VKD3DSI_SAMPLER_COMPARISON_MODE)
flags = VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE;
else
@@ -491,6 +598,9 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont
{
enum vkd3d_shader_descriptor_type type;
+ if (!context->scan_info)
+ return;
+
if (resource->reg.reg.type == VKD3DSPR_UAV)
type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
else
@@ -534,9 +644,10 @@ static void vkd3d_shader_scan_typed_resource_declaration(struct vkd3d_shader_sca
semantic->resource_type, resource_data_type);
}
-static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *context,
+static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *context,
const struct vkd3d_shader_instruction *instruction)
{
+ struct vkd3d_shader_cf_info *cf_info;
unsigned int i;
switch (instruction->handler_idx)
@@ -561,6 +672,121 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *cont
vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.structured_resource.resource,
VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT);
break;
+ case VKD3DSIH_IF:
+ cf_info = vkd3d_shader_scan_push_cf_info(context);
+ cf_info->type = VKD3D_SHADER_BLOCK_IF;
+ cf_info->inside_block = true;
+ break;
+ case VKD3DSIH_ELSE:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_IF)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘else’ instruction without corresponding ‘if’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = true;
+ break;
+ case VKD3DSIH_ENDIF:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_IF)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘endif’ instruction without corresponding ‘if’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ vkd3d_shader_scan_pop_cf_info(context);
+ break;
+ case VKD3DSIH_LOOP:
+ cf_info = vkd3d_shader_scan_push_cf_info(context);
+ cf_info->type = VKD3D_SHADER_BLOCK_LOOP;
+ break;
+ case VKD3DSIH_ENDLOOP:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_LOOP)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘endloop’ instruction without corresponding ‘loop’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ vkd3d_shader_scan_pop_cf_info(context);
+ break;
+ case VKD3DSIH_SWITCH:
+ cf_info = vkd3d_shader_scan_push_cf_info(context);
+ cf_info->type = VKD3D_SHADER_BLOCK_SWITCH;
+ break;
+ case VKD3DSIH_ENDSWITCH:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context))
+ || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH || cf_info->inside_block)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘endswitch’ instruction without corresponding ‘switch’ block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ vkd3d_shader_scan_pop_cf_info(context);
+ break;
+ case VKD3DSIH_CASE:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context))
+ || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘case’ instruction outside switch block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = true;
+ break;
+ case VKD3DSIH_DEFAULT:
+ if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context))
+ || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘default’ instruction outside switch block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ if (cf_info->has_default)
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered duplicate ‘default’ instruction inside the current switch block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = true;
+ cf_info->has_default = true;
+ break;
+ case VKD3DSIH_BREAK:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_breakable_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘break’ instruction outside breakable block.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = false;
+ break;
+ case VKD3DSIH_BREAKP:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘breakp’ instruction outside loop.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ break;
+ case VKD3DSIH_CONTINUE:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘continue’ instruction outside loop.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ cf_info->inside_block = false;
+ break;
+ case VKD3DSIH_CONTINUEP:
+ if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context)))
+ {
+ vkd3d_shader_error(&context->message_context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF,
+ "Encountered ‘continue’ instruction outside loop.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ break;
+ case VKD3DSIH_RET:
+ if (context->cf_info_count)
+ context->cf_info[context->cf_info_count - 1].inside_block = false;
+ break;
default:
break;
}
@@ -581,12 +807,14 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *cont
if (vkd3d_shader_instruction_is_uav_counter(instruction))
vkd3d_shader_scan_record_uav_counter(context, &instruction->src[0].reg);
+
+ return VKD3D_OK;
}
int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_scan_info *scan_info, char **messages)
{
- struct vkd3d_shader_message_context message_context;
+ struct vkd3d_shader_message_context *message_context;
struct vkd3d_shader_instruction instruction;
struct vkd3d_shader_scan_context context;
struct vkd3d_shader_parser parser;
@@ -603,24 +831,26 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
return VKD3D_ERROR_INVALID_ARGUMENT;
}
- if (!vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO, NULL))
+ if (!vkd3d_shader_scan_context_init(&context, scan_info))
return VKD3D_ERROR;
- ret = vkd3d_shader_parser_init(&parser, dxbc, &message_context);
- vkd3d_shader_message_context_trace_messages(&message_context);
- if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
- ret = VKD3D_ERROR_OUT_OF_MEMORY;
- vkd3d_shader_message_context_cleanup(&message_context);
- if (ret < 0)
+ message_context = &context.message_context;
+
+ if ((ret = vkd3d_shader_parser_init(&parser, dxbc, message_context)) < 0)
+ {
+ vkd3d_shader_message_context_trace_messages(message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_scan_context_cleanup(&context);
return ret;
+ }
if (TRACE_ON())
vkd3d_shader_trace(parser.data);
memset(scan_info, 0, sizeof(*scan_info));
- memset(&context, 0, sizeof(context));
- context.scan_info = scan_info;
-
+ message_context->line = 2; /* Line 1 is the version token. */
+ message_context->column = 1;
while (!shader_sm4_is_end(parser.data, &parser.ptr))
{
shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
@@ -628,18 +858,28 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
if (instruction.handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
- vkd3d_free(context.uav_ranges);
vkd3d_shader_free_scan_info(scan_info);
- vkd3d_shader_parser_destroy(&parser);
- return VKD3D_ERROR_INVALID_ARGUMENT;
+ ret = VKD3D_ERROR_INVALID_SHADER;
+ goto done;
}
- vkd3d_shader_scan_instruction(&context, &instruction);
+ if ((ret = vkd3d_shader_scan_instruction(&context, &instruction)) < 0)
+ {
+ vkd3d_shader_free_scan_info(scan_info);
+ goto done;
+ }
+ ++message_context->line;
}
- vkd3d_free(context.uav_ranges);
+ ret = VKD3D_OK;
+
+done:
+ vkd3d_shader_message_context_trace_messages(message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_scan_context_cleanup(&context);
vkd3d_shader_parser_destroy(&parser);
- return VKD3D_OK;
+ return ret;
}
void vkd3d_shader_free_scan_info(struct vkd3d_shader_scan_info *scan_info)
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index c6796bb..4fa17d6 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -67,6 +67,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
+ VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
};
enum VKD3D_SHADER_INSTRUCTION_HANDLER
--
2.11.0
1
0
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/dmime/timesigtrack.c | 54 +++++++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/dlls/dmime/timesigtrack.c b/dlls/dmime/timesigtrack.c
index 697b3e3593b..5bb38254d43 100644
--- a/dlls/dmime/timesigtrack.c
+++ b/dlls/dmime/timesigtrack.c
@@ -37,6 +37,11 @@ static inline IDirectMusicTimeSigTrack *impl_from_IDirectMusicTrack(IDirectMusic
return CONTAINING_RECORD(iface, IDirectMusicTimeSigTrack, IDirectMusicTrack_iface);
}
+static inline IDirectMusicTimeSigTrack *impl_from_IPersistStream(IPersistStream *iface)
+{
+ return CONTAINING_RECORD(iface, IDirectMusicTimeSigTrack, dmobj.IPersistStream_iface);
+}
+
static HRESULT WINAPI IDirectMusicTrackImpl_QueryInterface(IDirectMusicTrack *iface, REFIID riid,
void **ret_iface)
{
@@ -207,10 +212,55 @@ static const IDirectMusicTrackVtbl dmtack_vtbl = {
IDirectMusicTrackImpl_Clone
};
+
+static HRESULT parse_timetrack_list(IDirectMusicTimeSigTrack *This, IStream *stream,
+ struct chunk_entry *timesig)
+{
+ HRESULT hr;
+ struct chunk_entry chunk = {.parent = timesig};
+ DMUS_IO_TIMESIGNATURE_ITEM item;
+
+ TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(timesig));
+
+ while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
+ if (chunk.id != DMUS_FOURCC_TIMESIGNATURE_TRACK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &item, chunk.size))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
+ return hr;
+ }
+
+ TRACE("Found DMUS_IO_TIMESIGNATURE_ITEM\n");
+ TRACE(" - lTime %d\n", item.lTime);
+ TRACE(" - bBeatsPerMeasure %d\n", item.bBeatsPerMeasure);
+ TRACE(" - bBeat %d\n", item.bBeat);
+ TRACE(" - wGridsPerBeat %d\n", item.wGridsPerBeat);
+ }
+
+ return SUCCEEDED(hr) ? S_OK : hr;
+}
+
static HRESULT WINAPI time_IPersistStream_Load(IPersistStream *iface, IStream *stream)
{
- FIXME(": Loading not implemented yet\n");
- return S_OK;
+ IDirectMusicTimeSigTrack *This = impl_from_IPersistStream(iface);
+ HRESULT hr;
+ struct chunk_entry chunk = {0};
+
+ TRACE("%p, %p\n", This, stream);
+
+ if (!stream)
+ return E_POINTER;
+
+ if ((hr = stream_get_chunk(stream, &chunk) != S_OK))
+ return hr;
+
+ if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_TIMESIGTRACK_LIST)
+ hr = parse_timetrack_list(This, stream, &chunk);
+ else
+ hr = DMUS_E_UNSUPPORTED_STREAM;
+
+ return hr;
}
static const IPersistStreamVtbl persiststream_vtbl = {
--
2.27.0
1
0