HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, ID3DBlob **shader, ID3DBlob **error_messages) { HRESULT hr; ID3DBlob *buffer; TRACE("data %p, size %lu, filename %s, defines %p, include %p, shader %p, error_messages %p\n", data, size, debugstr_a(filename), defines, include, shader, error_messages); if (!data) return E_INVALIDARG; EnterCriticalSection(&wpp_mutex); if (shader) *shader = NULL; if (error_messages) *error_messages = NULL; hr = preprocess_shader(data, size, filename, defines, include, error_messages); if (SUCCEEDED(hr)) { if (shader) { hr = D3DCreateBlob(wpp_output_size, &buffer); if (FAILED(hr)) goto cleanup; CopyMemory(ID3D10Blob_GetBufferPointer(buffer), wpp_output, wpp_output_size); *shader = buffer; } else hr = E_INVALIDARG; } cleanup: HeapFree(GetProcessHeap(), 0, wpp_output); LeaveCriticalSection(&wpp_mutex); return hr; }
static HRESULT compile_shader(const char *preproc_shader, const char *target, const char *entrypoint, ID3DBlob **shader_blob, ID3DBlob **error_messages) { struct bwriter_shader *shader; char *messages = NULL; HRESULT hr; DWORD *res, size, major, minor; ID3DBlob *buffer; char *pos; enum shader_type shader_type; const struct target_info *info; TRACE("Preprocessed shader source: %s\n", debugstr_a(preproc_shader)); TRACE("Checking compilation target %s\n", debugstr_a(target)); info = get_target_info(target); if (!info) { FIXME("Unknown compilation target %s\n", debugstr_a(target)); return D3DERR_INVALIDCALL; } else { if (!info->support) { FIXME("Compilation target %s not yet supported\n", debugstr_a(target)); return D3DERR_INVALIDCALL; } else { shader_type = info->type; major = info->sm_major; minor = info->sm_minor; } } shader = parse_hlsl_shader(preproc_shader, shader_type, major, minor, entrypoint, &messages); if (messages) { TRACE("Compiler messages:\n"); TRACE("%s\n", debugstr_a(messages)); TRACE("Shader source:\n"); TRACE("%s\n", debugstr_a(preproc_shader)); if (error_messages) { const char *preproc_messages = *error_messages ? ID3D10Blob_GetBufferPointer(*error_messages) : NULL; size = strlen(messages) + (preproc_messages ? strlen(preproc_messages) : 0) + 1; hr = D3DCreateBlob(size, &buffer); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, messages); if (shader) SlDeleteShader(shader); return hr; } pos = ID3D10Blob_GetBufferPointer(buffer); if (preproc_messages) { memcpy(pos, preproc_messages, strlen(preproc_messages) + 1); pos += strlen(preproc_messages); } memcpy(pos, messages, strlen(messages) + 1); if (*error_messages) ID3D10Blob_Release(*error_messages); *error_messages = buffer; } HeapFree(GetProcessHeap(), 0, messages); } if (!shader) { ERR("HLSL shader parsing failed.\n"); return D3DXERR_INVALIDDATA; } hr = SlWriteBytecode(shader, 9, &res, &size); SlDeleteShader(shader); if (FAILED(hr)) { ERR("SlWriteBytecode failed with error 0x%08x.\n", hr); return D3DXERR_INVALIDDATA; } if (shader_blob) { hr = D3DCreateBlob(size, &buffer); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, res); return hr; } memcpy(ID3D10Blob_GetBufferPointer(buffer), res, size); *shader_blob = buffer; } HeapFree(GetProcessHeap(), 0, res); return S_OK; }
static HRESULT preprocess_shader(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, ID3DBlob **error_messages) { int ret; HRESULT hr = S_OK; const D3D_SHADER_MACRO *def = defines; static const struct wpp_callbacks wpp_callbacks = { wpp_lookup_mem, wpp_open_mem, wpp_close_mem, wpp_read_mem, wpp_write_mem, wpp_error, wpp_warning, }; if (def != NULL) { while (def->Name != NULL) { wpp_add_define(def->Name, def->Definition); def++; } } current_include = include; includes_size = 0; wpp_output_size = wpp_output_capacity = 0; wpp_output = NULL; wpp_set_callbacks(&wpp_callbacks); wpp_messages_size = wpp_messages_capacity = 0; wpp_messages = NULL; current_shader.buffer = data; current_shader.size = data_size; initial_filename = filename ? filename : ""; ret = wpp_parse(initial_filename, NULL); if (!wpp_close_output()) ret = 1; if (ret) { TRACE("Error during shader preprocessing\n"); if (wpp_messages) { int size; ID3DBlob *buffer; TRACE("Preprocessor messages:\n%s\n", debugstr_a(wpp_messages)); if (error_messages) { size = strlen(wpp_messages) + 1; hr = D3DCreateBlob(size, &buffer); if (FAILED(hr)) goto cleanup; CopyMemory(ID3D10Blob_GetBufferPointer(buffer), wpp_messages, size); *error_messages = buffer; } } if (data) TRACE("Shader source:\n%s\n", debugstr_an(data, data_size)); hr = E_FAIL; } cleanup: /* Remove the previously added defines */ if (defines != NULL) { while (defines->Name != NULL) { wpp_del_define(defines->Name); defines++; } } HeapFree(GetProcessHeap(), 0, wpp_messages); return hr; }
static HRESULT assemble_shader(const char *preproc_shader, ID3DBlob **shader_blob, ID3DBlob **error_messages) { struct bwriter_shader *shader; char *messages = NULL; HRESULT hr; DWORD *res, size; ID3DBlob *buffer; char *pos; shader = SlAssembleShader(preproc_shader, &messages); if (messages) { TRACE("Assembler messages:\n"); TRACE("%s\n", debugstr_a(messages)); TRACE("Shader source:\n"); TRACE("%s\n", debugstr_a(preproc_shader)); if (error_messages) { const char *preproc_messages = *error_messages ? ID3D10Blob_GetBufferPointer(*error_messages) : NULL; size = strlen(messages) + (preproc_messages ? strlen(preproc_messages) : 0) + 1; hr = D3DCreateBlob(size, &buffer); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, messages); if (shader) SlDeleteShader(shader); return hr; } pos = ID3D10Blob_GetBufferPointer(buffer); if (preproc_messages) { CopyMemory(pos, preproc_messages, strlen(preproc_messages) + 1); pos += strlen(preproc_messages); } CopyMemory(pos, messages, strlen(messages) + 1); if (*error_messages) ID3D10Blob_Release(*error_messages); *error_messages = buffer; } HeapFree(GetProcessHeap(), 0, messages); } if (shader == NULL) { ERR("Asm reading failed\n"); return D3DXERR_INVALIDDATA; } hr = SlWriteBytecode(shader, 9, &res, &size); SlDeleteShader(shader); if (FAILED(hr)) { ERR("SlWriteBytecode failed with 0x%08x\n", hr); return D3DXERR_INVALIDDATA; } if (shader_blob) { hr = D3DCreateBlob(size, &buffer); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, res); return hr; } CopyMemory(ID3D10Blob_GetBufferPointer(buffer), res, size); *shader_blob = buffer; } HeapFree(GetProcessHeap(), 0, res); return S_OK; }
HRESULT d3dcompiler_get_blob_part(const void *data, SIZE_T data_size, D3D_BLOB_PART part, UINT flags, ID3DBlob **blob) { struct dxbc src_dxbc, dst_dxbc; HRESULT hr; unsigned int i, count; if (!data || !data_size || flags || !blob) { WARN("Invalid arguments: data %p, data_size %lu, flags %#x, blob %p\n", data, data_size, flags, blob); return D3DERR_INVALIDCALL; } if (part > D3D_BLOB_TEST_COMPILE_PERF || (part < D3D_BLOB_TEST_ALTERNATE_SHADER && part > D3D_BLOB_XNA_SHADER)) { WARN("Invalid D3D_BLOB_PART: part %s\n", debug_d3dcompiler_d3d_blob_part(part)); return D3DERR_INVALIDCALL; } hr = dxbc_parse(data, data_size, &src_dxbc); if (FAILED(hr)) { WARN("Failed to parse blob part\n"); return hr; } hr = dxbc_init(&dst_dxbc, 0); if (FAILED(hr)) { dxbc_destroy(&src_dxbc); WARN("Failed to init dxbc\n"); return hr; } for (i = 0; i < src_dxbc.count; ++i) { struct dxbc_section *section = &src_dxbc.sections[i]; if (check_blob_part(section->tag, part)) { hr = dxbc_add_section(&dst_dxbc, section->tag, section->data, section->data_size); if (FAILED(hr)) { dxbc_destroy(&src_dxbc); dxbc_destroy(&dst_dxbc); WARN("Failed to add section to dxbc\n"); return hr; } } } count = dst_dxbc.count; switch(part) { case D3D_BLOB_INPUT_SIGNATURE_BLOB: case D3D_BLOB_OUTPUT_SIGNATURE_BLOB: case D3D_BLOB_PATCH_CONSTANT_SIGNATURE_BLOB: case D3D_BLOB_DEBUG_INFO: case D3D_BLOB_LEGACY_SHADER: case D3D_BLOB_XNA_PREPASS_SHADER: case D3D_BLOB_XNA_SHADER: if (count != 1) count = 0; break; case D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB: if (count != 2) count = 0; break; case D3D_BLOB_ALL_SIGNATURE_BLOB: if (count != 3) count = 0; break; default: FIXME("Unhandled D3D_BLOB_PART %s.\n", debug_d3dcompiler_d3d_blob_part(part)); break; } if (count == 0) { dxbc_destroy(&src_dxbc); dxbc_destroy(&dst_dxbc); WARN("Nothing to write into the blob (count = 0)\n"); return E_FAIL; } /* some parts aren't full DXBCs, they contain only the data */ if (count == 1 && (part == D3D_BLOB_DEBUG_INFO || part == D3D_BLOB_LEGACY_SHADER || part == D3D_BLOB_XNA_PREPASS_SHADER || part == D3D_BLOB_XNA_SHADER)) { hr = D3DCreateBlob(dst_dxbc.sections[0].data_size, blob); if (SUCCEEDED(hr)) { memcpy(ID3D10Blob_GetBufferPointer(*blob), dst_dxbc.sections[0].data, dst_dxbc.sections[0].data_size); } else { WARN("Could not create blob\n"); } } else { hr = dxbc_write_blob(&dst_dxbc, blob); if (FAILED(hr)) { WARN("Failed to write blob part\n"); } } dxbc_destroy(&src_dxbc); dxbc_destroy(&dst_dxbc); return hr; }