[1/3] d3dx9: Partial implementation of D3DXAssembleShader function.
Matteo Bruni
matteo.mystral at gmail.com
Tue Feb 2 11:11:44 CST 2010
Hello,
here is a new iteration of the main patches for the d3dx9 shader
assembler. This should address Henri's previous comments (mainly
http://www.winehq.org/pipermail/wine-devel/2009-December/080845.html);
I also reverted to a non-reentrant lexer, the reentrancy wasn't really
needed anyway.
-------------- next part --------------
From a6b0105cda1c46e2cb8b41c1586bfe06b29f8015 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Tue, 2 Feb 2010 15:56:30 +0100
Subject: d3dx9: Partial implementation of D3DXAssembleShader function.
This only executes the preprocessing pass. No parsing of the shader yet.
---
dlls/d3dx9_36/Makefile.in | 1 +
dlls/d3dx9_36/shader.c | 325 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 325 insertions(+), 1 deletions(-)
diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in
index 88ac1d7..a2ad690 100644
--- a/dlls/d3dx9_36/Makefile.in
+++ b/dlls/d3dx9_36/Makefile.in
@@ -5,6 +5,7 @@ VPATH = @srcdir@
MODULE = d3dx9_36.dll
IMPORTLIB = d3dx9
IMPORTS = d3d9 gdi32 user32 kernel32
+EXTRALIBS = $(LIBWPP) $(LIBPORT)
C_SRCS = \
core.c \
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index c05f7b7..3461eba 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -1,5 +1,6 @@
/*
* Copyright 2008 Luis Busquets
+ * Copyright 2009 Matteo Bruni
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +24,7 @@
#include "windef.h"
#include "wingdi.h"
#include "d3dx9.h"
+#include "wine/wpp.h"
#include "d3dx9_36_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
@@ -134,6 +136,228 @@ LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
return NULL;
}
+#define MESSAGEBUFFER_INITIAL_SIZE 256
+#define BUFFER_INITIAL_CAPACITY 256
+
+struct mem_file_desc
+{
+ char *buffer;
+ unsigned int size;
+ unsigned int pos;
+};
+
+struct mem_file_desc current_shader;
+LPD3DXINCLUDE current_include;
+char *wpp_output;
+int wpp_output_capacity, wpp_output_size;
+
+char *wpp_messages;
+int wpp_messages_capacity, wpp_messages_size;
+
+/* Mutex used to guarantee a single invocation
+ of the D3DXAssembleShader function (or its variants) at a time.
+ This is needed as wpp isn't thread-safe */
+static CRITICAL_SECTION wpp_mutex;
+static CRITICAL_SECTION_DEBUG wpp_mutex_debug =
+{
+ 0, 0, &wpp_mutex,
+ { &wpp_mutex_debug.ProcessLocksList,
+ &wpp_mutex_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": wpp_mutex") }
+};
+static CRITICAL_SECTION wpp_mutex = { &wpp_mutex_debug, -1, 0, 0, 0, 0 };
+
+/* Preprocessor error reporting functions */
+void wpp_write_message(const char *fmt, va_list args)
+{
+ char* newbuffer;
+ int rc, newsize;
+
+ if(wpp_messages_capacity == 0)
+ {
+ wpp_messages = HeapAlloc(GetProcessHeap(), 0, MESSAGEBUFFER_INITIAL_SIZE);
+ if(wpp_messages == NULL)
+ {
+ ERR("Error allocating memory for parser messages\n");
+ return;
+ }
+ wpp_messages_capacity = MESSAGEBUFFER_INITIAL_SIZE;
+ }
+
+ while(1)
+ {
+ rc = vsnprintf(wpp_messages + wpp_messages_size,
+ wpp_messages_capacity - wpp_messages_size, fmt, args);
+
+ if (rc < 0 || /* C89 */
+ rc >= wpp_messages_capacity - wpp_messages_size) { /* C99 */
+ /* Resize the buffer */
+ newsize = wpp_messages_capacity * 2;
+ newbuffer = HeapReAlloc(GetProcessHeap(), 0, wpp_messages, newsize);
+ if(newbuffer == NULL)
+ {
+ ERR("Error reallocating memory for parser messages\n");
+ return;
+ }
+ wpp_messages = newbuffer;
+ wpp_messages_capacity = newsize;
+ }
+ else
+ {
+ wpp_messages_size += rc;
+ return;
+ }
+ }
+}
+
+void wpp_write_message_var(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ wpp_write_message(fmt, args);
+ va_end(args);
+}
+
+void wpp_error(const char *file, int line, int col, const char *near,
+ const char *msg, va_list ap)
+{
+ wpp_write_message_var("%s:%d:%d: %s: ", file ? file : "'main file'",
+ line, col, "Error");
+ wpp_write_message(msg, ap);
+ wpp_write_message_var("\n");
+}
+
+void wpp_warning(const char *file, int line, int col, const char *near,
+ const char *msg, va_list ap)
+{
+ wpp_write_message_var("%s:%d:%d: %s: ", file ? file : "'main file'",
+ line, col, "Warning");
+ wpp_write_message(msg, ap);
+ wpp_write_message_var("\n");
+}
+
+char *wpp_lookup_mem(const char *filename, const char *parent_name,
+ char **include_path, int include_path_count)
+{
+ /* Here we return always ok. We will maybe fail on the next wpp_open_mem */
+ char *path;
+
+ path = malloc(strlen(filename) + 1);
+ if(!path) return NULL;
+ memcpy(path, filename, strlen(filename) + 1);
+ return path;
+}
+
+void *wpp_open_mem(const char *filename, int type)
+{
+ struct mem_file_desc *desc;
+
+ if(filename[0] == '\0') /* "" means to load the initial shader */
+ {
+ current_shader.pos = 0;
+ return ¤t_shader;
+ }
+ else
+ {
+ HRESULT hr;
+
+ if(current_include == NULL) return NULL;
+ desc = HeapAlloc(GetProcessHeap(), 0, sizeof(struct mem_file_desc));
+ if(!desc)
+ {
+ ERR("Error allocating memory\n");
+ return NULL;
+ }
+ hr = ID3DXInclude_Open(current_include,
+ type ? D3DXINC_SYSTEM : D3DXINC_LOCAL,
+ filename, NULL, (LPCVOID *)&desc->buffer,
+ &desc->size);
+ if(FAILED(hr))
+ {
+ HeapFree(GetProcessHeap(), 0, desc);
+ return NULL;
+ }
+ }
+ desc->pos = 0;
+ return desc;
+}
+
+void wpp_close_mem(void *file)
+{
+ struct mem_file_desc *desc = file;
+
+ if(desc != ¤t_shader)
+ {
+ if(current_include == NULL)
+ {
+ ERR("current_include == NULL, desc == %p, buffer = %s\n",
+ desc, desc->buffer);
+ HeapFree(GetProcessHeap(), 0, desc);
+ return;
+ }
+ ID3DXInclude_Close(current_include, desc->buffer);
+ HeapFree(GetProcessHeap(), 0, desc);
+ return;
+ }
+ /* This is the main file */
+ HeapFree(GetProcessHeap(), 0, desc->buffer);
+ desc->buffer = NULL;
+}
+
+int wpp_read_mem(void *file, char *buffer, unsigned int len)
+{
+ struct mem_file_desc *desc = file;
+
+ if(desc->pos + len > desc->size) len = desc->size - desc->pos;
+ memcpy(buffer, &desc->buffer[desc->pos], len);
+ desc->pos += len;
+ return len;
+}
+
+void wpp_write_mem(const char *buffer, unsigned int len)
+{
+ char *new_wpp_output;
+
+ if(wpp_output_capacity == 0)
+ {
+ wpp_output = HeapAlloc(GetProcessHeap(), 0, BUFFER_INITIAL_CAPACITY);
+ if(!wpp_output)
+ {
+ ERR("Error allocating memory\n");
+ return;
+ }
+ wpp_output_capacity = BUFFER_INITIAL_CAPACITY;
+ }
+ if(wpp_output_size + len > wpp_output_capacity)
+ {
+ while(wpp_output_size + len > wpp_output_capacity)
+ {
+ wpp_output_capacity *= 2;
+ }
+ new_wpp_output = HeapReAlloc(GetProcessHeap(), 0, wpp_output,
+ wpp_output_capacity);
+ if(!new_wpp_output)
+ {
+ ERR("Error allocating memory\n");
+ return;
+ }
+ wpp_output = new_wpp_output;
+ }
+ memcpy(wpp_output+wpp_output_size, buffer, len);
+ wpp_output_size += len;
+}
+
+int wpp_close_output(void)
+{
+ /* trim buffer to the effective size */
+ char *new_wpp_output = HeapReAlloc(GetProcessHeap(), 0, wpp_output,
+ wpp_output_size + 1);
+ if(!new_wpp_output) return 0;
+ wpp_output[wpp_output_size]='\0';
+ return 1;
+}
+
HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
UINT data_len,
CONST D3DXMACRO* defines,
@@ -142,8 +366,107 @@ HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
LPD3DXBUFFER* shader,
LPD3DXBUFFER* error_messages)
{
+ int ret;
+ HRESULT hr;
+ CONST D3DXMACRO* def = defines;
+
+ struct wpp_callbacks wpp_callbacks = {
+ wpp_lookup_mem,
+ wpp_open_mem,
+ wpp_close_mem,
+ wpp_read_mem,
+ wpp_write_mem,
+ wpp_error,
+ wpp_warning,
+ };
+
+ EnterCriticalSection(&wpp_mutex);
+
+ /* TODO: flags */
+ if(flags) FIXME("flags: %x\n", flags);
+
+ if(def != NULL)
+ {
+ while(def->Name != NULL)
+ {
+ wpp_add_define(def->Name, def->Definition);
+ def++;
+ }
+ }
+ current_include = include;
+
+ *shader = *error_messages = NULL;
+ wpp_output_size = wpp_output_capacity = 0;
+ wpp_output = NULL;
+
+ /* Preprocess shader */
+ wpp_set_callbacks(&wpp_callbacks);
+ wpp_messages_size = wpp_messages_capacity = 0;
+ wpp_messages = NULL;
+ current_shader.buffer = HeapAlloc(GetProcessHeap(), 0, data_len + 1);
+ if(!current_shader.buffer)
+ {
+ ERR("Not enough free memory\n");
+ hr = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+ memcpy(current_shader.buffer, data, data_len);
+ current_shader.buffer[data_len] = '\0';
+ current_shader.size = data_len;
+
+ ret = wpp_parse("", NULL);
+ if(!wpp_close_output())
+ ret = 1;
+ if(ret)
+ {
+ int i;
+
+ TRACE("Error during shader preprocessing\n");
+ HeapFree(GetProcessHeap(), 0, current_shader.buffer);
+ if(wpp_messages)
+ {
+ int size;
+ LPD3DXBUFFER buffer;
+
+ TRACE("Preprocessor messages:\n");
+ TRACE("%s", wpp_messages);
+
+ size = strlen(wpp_messages) + 1;
+ hr = D3DXCreateBuffer(size, &buffer);
+ if(FAILED(hr)) goto cleanup;
+ CopyMemory(ID3DXBuffer_GetBufferPointer(buffer), wpp_messages, size);
+ *error_messages = buffer;
+ }
+ if(data)
+ {
+ TRACE("Shader source:\n");
+ for(i=0;i<data_len;i++)
+ {
+ TRACE("%c", data[i]);
+ }
+ TRACE("\n");
+ }
+ hr = D3DXERR_INVALIDDATA;
+ goto cleanup;
+ }
+
FIXME("stub\n");
- return D3DERR_INVALIDCALL;
+ hr = D3DERR_INVALIDCALL;
+
+cleanup:
+ /* Remove the previously added defines */
+ if(defines != NULL)
+ {
+ while(defines->Name != NULL)
+ {
+ wpp_del_define(defines->Name);
+ defines++;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, wpp_messages);
+ HeapFree(GetProcessHeap(), 0, wpp_output);
+ LeaveCriticalSection(&wpp_mutex);
+ return hr;
}
HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
--
1.6.4.4
More information about the wine-patches
mailing list