static p_file *CopyProlog(const char *name, const char *title) { p_file *psps= GistOpen("ps.ps"); p_file *file= strcmp(name, "*stdout*")? CREATE_PS(name) : pf_stdout; if (!psps) strcpy(gistError, "unable to open PostScript prolog ps.ps"); if (!file) strcpy(gistError, "unable to create PostScript output file"); if (psps && file) { titleIs= title; needUser= needDate= 1; for (;;) { if (!p_fgets(psps, line, 79) || PutPrologLine(file)<0) { if (file!=pf_stdout) p_fclose(file); file= 0; strcpy(gistError, "bad PostScript prolog format in ps.ps??"); break; } if (strncmp(line, "%%EndSetup", 10L)==0) break; } } else if (file) { if (file!=pf_stdout) p_fclose(file); file= 0; } if (psps) p_fclose(psps); return file; }
EGDevice egCreateDevice(HWND windowHandle) { if (pBoundDevice) { if (pBoundDevice->bIsInBatch) return 0; } EGDevice ret = 0; DXGI_SWAP_CHAIN_DESC swapChainDesc; HRESULT result; ID3D11Texture2D *pBackBuffer; ID3D11Resource *pBackBufferRes; ID3D11Texture2D *pDepthStencilBuffer; // Set as currently bound device devices = realloc(devices, sizeof(SEGDevice) * (deviceCount + 1)); memset(devices + deviceCount, 0, sizeof(SEGDevice)); pBoundDevice = devices + deviceCount; ++deviceCount; ret = deviceCount; // Define our swap chain memset(&swapChainDesc, 0, sizeof(swapChainDesc)); swapChainDesc.BufferCount = 1; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = windowHandle; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; // Create the swap chain, device and device context result = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, #if _DEBUG D3D11_CREATE_DEVICE_DEBUG, #else /* _DEBUG */ 0, #endif /* _DEBUG */ NULL, 0, D3D11_SDK_VERSION, &swapChainDesc, &pBoundDevice->pSwapChain, &pBoundDevice->pDevice, NULL, &pBoundDevice->pDeviceContext); if (result != S_OK) { setError("Failed D3D11CreateDeviceAndSwapChain"); egDestroyDevice(&ret); return 0; } // Create render target result = pBoundDevice->pSwapChain->lpVtbl->GetBuffer(pBoundDevice->pSwapChain, 0, &IID_ID3D11Texture2D, (void**)&pBackBuffer); if (result != S_OK) { setError("Failed IDXGISwapChain GetBuffer IID_ID3D11Texture2D"); egDestroyDevice(&ret); return 0; } result = pBoundDevice->pSwapChain->lpVtbl->GetBuffer(pBoundDevice->pSwapChain, 0, &IID_ID3D11Resource, (void**)&pBackBufferRes); if (result != S_OK) { setError("Failed IDXGISwapChain GetBuffer IID_ID3D11Resource"); egDestroyDevice(&ret); return 0; } result = pBoundDevice->pDevice->lpVtbl->CreateRenderTargetView(pBoundDevice->pDevice, pBackBufferRes, NULL, &pBoundDevice->pRenderTargetView); if (result != S_OK) { setError("Failed CreateRenderTargetView"); egDestroyDevice(&ret); return 0; } pBackBuffer->lpVtbl->GetDesc(pBackBuffer, &pBoundDevice->backBufferDesc); pBackBufferRes->lpVtbl->Release(pBackBufferRes); pBackBuffer->lpVtbl->Release(pBackBuffer); // Set up the description of the depth buffer. D3D11_TEXTURE2D_DESC depthBufferDesc = {0}; depthBufferDesc.Width = pBoundDevice->backBufferDesc.Width; depthBufferDesc.Height = pBoundDevice->backBufferDesc.Height; depthBufferDesc.MipLevels = 1; depthBufferDesc.ArraySize = 1; depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.SampleDesc.Quality = 0; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthBufferDesc.CPUAccessFlags = 0; depthBufferDesc.MiscFlags = 0; // Create the texture for the depth buffer using the filled out description. result = pBoundDevice->pDevice->lpVtbl->CreateTexture2D(pBoundDevice->pDevice, &depthBufferDesc, NULL, &pDepthStencilBuffer); if (result != S_OK) { setError("Failed DepthStencil CreateTexture2D"); egDestroyDevice(&ret); return 0; } // Initailze the depth stencil view. D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {0}; depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; // Create the depth stencil view. result = pDepthStencilBuffer->lpVtbl->QueryInterface(pDepthStencilBuffer, &IID_ID3D11Resource, (void**)&pBackBufferRes); if (result != S_OK) { setError("Failed DepthStencil ID3D11Texture2D QueryInterface IID_ID3D11Resource"); egDestroyDevice(&ret); return 0; } result = pBoundDevice->pDevice->lpVtbl->CreateDepthStencilView(pBoundDevice->pDevice, pBackBufferRes, &depthStencilViewDesc, &pBoundDevice->pDepthStencilView); if (result != S_OK) { setError("Failed CreateDepthStencilView"); egDestroyDevice(&ret); return 0; } pBackBufferRes->lpVtbl->Release(pBackBufferRes); pDepthStencilBuffer->lpVtbl->Release(pDepthStencilBuffer); // Compile vertex shaders and related input layouts { ID3DBlob *pCompiled; CREATE_VS(g_vs, &pBoundDevice->pVS, pCompiled); D3D11_INPUT_ELEMENT_DESC layout[6] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 56, D3D11_INPUT_PER_VERTEX_DATA, 0} }; result = pBoundDevice->pDevice->lpVtbl->CreateInputLayout(pBoundDevice->pDevice, layout, 6, pCompiled->lpVtbl->GetBufferPointer(pCompiled), pCompiled->lpVtbl->GetBufferSize(pCompiled), &pBoundDevice->pInputLayout); if (result != S_OK) { setError("Failed CreateInputLayout"); egDestroyDevice(&ret); return 0; } pCompiled->lpVtbl->Release(pCompiled); } { ID3DBlob *pCompiled; CREATE_VS(g_vsPassThrough, &pBoundDevice->pVSPassThrough, pCompiled); D3D11_INPUT_ELEMENT_DESC layout[3] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 56, D3D11_INPUT_PER_VERTEX_DATA, 0} }; result = pBoundDevice->pDevice->lpVtbl->CreateInputLayout(pBoundDevice->pDevice, layout, 3, pCompiled->lpVtbl->GetBufferPointer(pCompiled), pCompiled->lpVtbl->GetBufferSize(pCompiled), &pBoundDevice->pInputLayoutPassThrough); if (result != S_OK) { setError("Failed CreateInputLayout PassThrough"); egDestroyDevice(&ret); return 0; } pCompiled->lpVtbl->Release(pCompiled); } // Pixel shaders for (int i = 0; i < 18; ++i) { CREATE_PS(g_pses[i], &(pBoundDevice->pPSes[i])); } pBoundDevice->pActivePS = pBoundDevice->pPSes[0]; CREATE_PS(g_psPassThrough, &pBoundDevice->pPSPassThrough); CREATE_PS(g_psLDR, &pBoundDevice->pPSLDR); CREATE_PS(g_psAmbient, &pBoundDevice->pPSAmbient); CREATE_PS(g_psOmni, &pBoundDevice->pPSOmni); CREATE_PS(g_psBlurH, &pBoundDevice->pPSBlurH); CREATE_PS(g_psBlurV, &pBoundDevice->pPSBlurV); for (int i = 0; i < 2; ++i) { CREATE_PS(g_psPostProcess[i], &(pBoundDevice->pPSPostProcess[i])); } // Create uniforms { D3D11_BUFFER_DESC cbDesc = {64, D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, 0, 0}; result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &cbDesc, NULL, &pBoundDevice->pCBViewProj); if (result != S_OK) { setError("Failed CreateBuffer CBViewProj"); egDestroyDevice(&ret); return 0; } result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &cbDesc, NULL, &pBoundDevice->pCBModel); if (result != S_OK) { setError("Failed CreateBuffer CBModel"); egDestroyDevice(&ret); return 0; } result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &cbDesc, NULL, &pBoundDevice->pCBInvViewProj); if (result != S_OK) { setError("Failed CreateBuffer CBInvViewProj"); egDestroyDevice(&ret); return 0; } } { D3D11_BUFFER_DESC cbDesc = {sizeof(SEGOmni), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, 0, 0}; result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &cbDesc, NULL, &pBoundDevice->pCBOmni); if (result != S_OK) { setError("Failed CreateBuffer CBInvViewProj"); egDestroyDevice(&ret); return 0; } } { D3D11_BUFFER_DESC cbDesc = {sizeof(float) * 4, D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, 0, 0}; float initialRef[4] = {.5f, 4.f, 0, 0}; D3D11_SUBRESOURCE_DATA initialData = {initialRef, 0, 0}; result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &cbDesc, &initialData, &pBoundDevice->pCBAlphaTestRef); if (result != S_OK) { setError("Failed CreateBuffer CBAlphaTestRef"); egDestroyDevice(&ret); return 0; } pBoundDevice->pDeviceContext->lpVtbl->PSSetConstantBuffers(pBoundDevice->pDeviceContext, 2, 1, &pBoundDevice->pCBAlphaTestRef); } { D3D11_BUFFER_DESC cbDesc = {sizeof(float) * 4, D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, 0, 0}; result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &cbDesc, NULL, &pBoundDevice->pCBBlurSpread); if (result != S_OK) { setError("Failed CreateBuffer CBBlurSpread"); egDestroyDevice(&ret); return 0; } } // Create our geometry batch vertex buffer that will be used to batch everything D3D11_BUFFER_DESC vertexBufferDesc; vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0; pBoundDevice->pCurrentBatchVertices = (SEGVertex *)malloc(sizeof(SEGVertex) * MAX_VERTEX_COUNT); for (UINT i = 0; i < VERTEX_BUFFER_COUNT; ++i) { UINT vertCount = (UINT)pow(2, 8 + (double)i); vertexBufferDesc.ByteWidth = vertCount * sizeof(SEGVertex); result = pBoundDevice->pDevice->lpVtbl->CreateBuffer(pBoundDevice->pDevice, &vertexBufferDesc, NULL, &pBoundDevice->pVertexBuffers[i]); if (result != S_OK) { setError("Failed CreateBuffer VertexBuffer"); egDestroyDevice(&ret); return 0; } result = pBoundDevice->pVertexBuffers[i]->lpVtbl->QueryInterface(pBoundDevice->pVertexBuffers[i], &IID_ID3D11Resource, &pBoundDevice->pVertexBufferResources[i]); if (result != S_OK) { setError("Failed VertexBuffer ID3D11Buffer QueryInterface -> IID_ID3D11Resource"); egDestroyDevice(&ret); return 0; } } // Create default textures { uint8_t pixel[4] = {255, 255, 255, 255}; texture2DFromData(pBoundDevice->pDefaultTextureMaps + DIFFUSE_MAP, pixel, 1, 1, FALSE); if (!pBoundDevice->pDefaultTextureMaps[DIFFUSE_MAP].pTexture) { egDestroyDevice(&ret); return 0; } } { uint8_t pixel[4] = {128, 128, 255, 255}; texture2DFromData(pBoundDevice->pDefaultTextureMaps + NORMAL_MAP, pixel, 1, 1, FALSE); if (!pBoundDevice->pDefaultTextureMaps[NORMAL_MAP].pTexture) { egDestroyDevice(&ret); return 0; } } { uint8_t pixel[4] = {0, 1, 0, 0}; texture2DFromData(pBoundDevice->pDefaultTextureMaps + MATERIAL_MAP, pixel, 1, 1, FALSE); if (!pBoundDevice->pDefaultTextureMaps[MATERIAL_MAP].pTexture) { egDestroyDevice(&ret); return 0; } } { uint8_t pixel[4] = {0, 0, 0, 0}; texture2DFromData(&pBoundDevice->transparentBlackTexture, pixel, 1, 1, FALSE); if (!pBoundDevice->transparentBlackTexture.pTexture) { egDestroyDevice(&ret); return 0; } } // Create our G-Buffer result = createRenderTarget(pBoundDevice->gBuffer + G_DIFFUSE, pBoundDevice->backBufferDesc.Width, pBoundDevice->backBufferDesc.Height, DXGI_FORMAT_R8G8B8A8_UNORM); if (result != S_OK) { egDestroyDevice(&ret); return 0; } result = createRenderTarget(pBoundDevice->gBuffer + G_DEPTH, pBoundDevice->backBufferDesc.Width, pBoundDevice->backBufferDesc.Height, DXGI_FORMAT_R32_FLOAT); if (result != S_OK) { egDestroyDevice(&ret); return 0; } result = createRenderTarget(pBoundDevice->gBuffer + G_NORMAL, pBoundDevice->backBufferDesc.Width, pBoundDevice->backBufferDesc.Height, DXGI_FORMAT_R8G8B8A8_UNORM); if (result != S_OK) { egDestroyDevice(&ret); return 0; } result = createRenderTarget(pBoundDevice->gBuffer + G_MATERIAL, pBoundDevice->backBufferDesc.Width, pBoundDevice->backBufferDesc.Height, DXGI_FORMAT_R8G8B8A8_UNORM); if (result != S_OK) { egDestroyDevice(&ret); return 0; } // Accumulation buffer. This is an HDR texture result = createRenderTarget(&pBoundDevice->accumulationBuffer, pBoundDevice->backBufferDesc.Width, pBoundDevice->backBufferDesc.Height, DXGI_FORMAT_R16G16B16A16_FLOAT); // DXGI_FORMAT_R11G11B10_FLOAT if (result != S_OK) { egDestroyDevice(&ret); return 0; } // Create blur buffers for (int i = 0; i < 8; ++i) { UINT divider = (UINT)pow(2, (double)i); for (int k = 0; k < 2; ++k) { UINT w = pBoundDevice->backBufferDesc.Width / divider; UINT h = pBoundDevice->backBufferDesc.Height / divider; result = createRenderTarget(&pBoundDevice->blurBuffers[i][k], w, h, DXGI_FORMAT_R8G8B8A8_UNORM); if (result != S_OK) { egDestroyDevice(&ret); return 0; } } } resetState(); // Create some internal states { egDisable(EG_ALL); egEnable(EG_BLEND); egBlendFunc(EG_ONE, EG_ONE); pBoundDevice->passStates[EG_AMBIENT_PASS] = egCreateState(); pBoundDevice->passStates[EG_OMNI_PASS] = egCreateState(); SEGState *pState = pBoundDevice->states + (pBoundDevice->passStates[EG_AMBIENT_PASS] - 1); pState->ignoreBits = STATE_ALPHA_TEST | STATE_VIGNETTE; pState = pBoundDevice->states + (pBoundDevice->passStates[EG_OMNI_PASS] - 1); pState->ignoreBits = STATE_ALPHA_TEST | STATE_VIGNETTE; } { egDisable(EG_ALL); egFilter(EG_FILTER_MIN_MAG_LINEAR_MIP_POINT); SEGState *pState = pBoundDevice->stateStack + pBoundDevice->statesStackCount; pState->samplerState.desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; pState->samplerState.desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; pState->samplerState.desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; pState->samplerState.desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; pState->samplerState.desc.MaxLOD = D3D11_FLOAT32_MAX; pBoundDevice->passStates[EG_POST_PROCESS_PASS] = egCreateState(); pState = pBoundDevice->states + (pBoundDevice->passStates[EG_POST_PROCESS_PASS] - 1); pState->ignoreBits = STATE_ALPHA_TEST | STATE_VIGNETTE; } resetState(); return ret; }