On Wednesday 04 August 2010 04:17:15 Chia-I Wu wrote: > I've updated the geometry shader so that given a triangle with adjacency, 3 > triangles will be emitted: > > - the triangle formed by the first edge and the first adjacent vertex > - the triangle formed by the second edge and the second adjacent vertex > - the triangle formed by the third edge and the third adjacent vertex > > and the color is decided by the respective adjacent vertices. > > The vertex array is updated to consist of 8 vertices (2 triangles), which > layout just like the diagram in the D3D doc, except the diagram has 14 > vertices (5 triangles). The color of the adjacent vertices for the first > and second triangles are red and green respectively. > > With this setup, you can find the results of the running the demo with > master and draw-decompose-2 branches, and with nVidia's driver on Windows. > > This says nothing about D3D triangle strip with adjacency, but it now seems > to follow wat nVidia's OpenGL driver does.
Nice job! That looks pretty good, I ported the example to D3D to see what it does. It looks like at least the right vertices are being used. On my NVIDIA linux setup it looks like D3D flips the verts in the second triangle (as we expected). Compare tristripadj8.png to what the GL version of my example does with glDrawArrays(..., 0, 8) and tristripadj10.png to glDrawArrays(..., 0, 10). Attached is the D3D example that I used (just change the Vertex data to the data from my example to see it since right now it uses the data from yours and that looks the same on d3d windows as it does on gl). It accepts "-reference" flag which will use Windows reference rasterizer. z
#include <initguid.h> #include <windows.h> #include <d3dx10.h> #include <d3d10.h> #include <cassert> #include <stdio.h> static void Render(); static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: Render(); ValidateRect(hWnd, NULL); InvalidateRect(hWnd, NULL, FALSE); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; } const LPCTSTR WINDOW_CLASS = TEXT("gsdjtri.window"); const DWORD WINDOW_STYLE = WS_OVERLAPPEDWINDOW; const DWORD WINDOW_EXSTYLE = 0; const LPCTSTR WINDOW_TITLE = TEXT("gsadjtri"); const DWORD WINDOW_WIDTH = 256; const DWORD WINDOW_HEIGHT = 256; static HWND hWnd = NULL; static ID3D10Device* pD3D10Device = NULL; static IDXGISwapChain* pSwapChain = NULL; static ID3D10RenderTargetView* pRenderTargetView = NULL; static ID3D10Blob* pVSBuffer = NULL; static ID3D10VertexShader* pVertexShader = NULL; static const char tadj_vsh[] = "\ struct SInput {\n\ float4 position : position;\n\ float4 color : color;\n\ };\n\ \n\ struct SOutput {\n\ float4 position : SV_Position;\n\ float4 color : color;\n\ };\n\ \n\ SOutput main(SInput input)\n\ {\n\ SOutput output;\n\ \n\ output.position = input.position;\n\ output.color = input.color;\n\ \n\ return output;\n\ }\n\ "; static ID3D10GeometryShader* pGeometryShader = NULL; static const char tadj_gsh[] = "\ struct Input {\n\ float4 position : SV_Position;\n\ float4 color : color;\n\ };\n\ \n\ struct Output {\n\ float4 position : SV_Position;\n\ float4 color : color;\n\ };\n\ \n\ [maxvertexcount(64)]\n\ void\n\ main(triangleadj Input input[6],\n\ inout TriangleStream<Output> output)\n\ {\n\ Output vertex;\n\ \n\ vertex.position = input[0].position;\n\ vertex.color = input[1].color;\n \ output.Append(vertex);\n\ vertex.position = input[1].position;\n\ vertex.color = input[1].color;\n \ output.Append(vertex);\n\ vertex.position = input[2].position;\n\ vertex.color = input[1].color;\n \ output.Append(vertex);\n\ output.RestartStrip();\n\ \n\ vertex.position = input[2].position;\n\ vertex.color = input[3].color;\n \ output.Append(vertex);\n\ vertex.position = input[3].position;\n\ vertex.color = input[3].color;\n \ output.Append(vertex);\n\ vertex.position = input[4].position;\n\ vertex.color = input[3].color;\n \ output.Append(vertex);\n\ output.RestartStrip();\n\ \n\ vertex.position = input[4].position;\n\ vertex.color = input[5].color;\n \ output.Append(vertex);\n\ vertex.position = input[5].position;\n\ vertex.color = input[5].color;\n \ output.Append(vertex);\n\ vertex.position = input[0].position;\n\ vertex.color = input[5].color;\n \ output.Append(vertex);\n\ output.RestartStrip();\n\ }\n\ "; static ID3D10PixelShader* pPixelShader = NULL; static const char tadj_psh[] = "\ struct SInput {\n\ float4 position : SV_Position;\n\ float4 color : color;\n\ };\n\ \n\ struct SOutput {\n\ float4 color : SV_Target;\n\ };\n\ \n\ SOutput main(SInput input)\n\ {\n\ SOutput output;\n\ \n\ output.color = input.color;\n\ return output;\n\ }\n\ "; static ID3D10Buffer* pVertexBufferTadj = NULL; static ID3D10InputLayout* pVertexLayout = NULL; struct Vertex { float position[4]; float color[4]; }; #define TRI0_ADJ_COLOR { 1.0f, 0.0f, 0.0f, 1.0f } #define TRI1_ADJ_COLOR { 0.0f, 1.0f, 0.0f, 1.0f } #define OTHERS_COLOR { 0.0f, 0.0f, 1.0f, 1.0f } const struct Vertex vTri[8] = { { { -0.6f, -0.33f, 0.5f, 1.0f }, TRI1_ADJ_COLOR }, /* 0 */ { { -1.0f, 0.33f, 0.5f, 1.0f }, TRI0_ADJ_COLOR }, /* 1 */ { { -0.2f, 0.33f, 0.5f, 1.0f }, OTHERS_COLOR }, /* 2 */ { { -0.2f, -1.0f, 0.5f, 1.0f }, TRI0_ADJ_COLOR }, /* 3 */ { { 0.2f, -0.33f, 0.5f, 1.0f }, OTHERS_COLOR }, /* 4 */ { { 0.2f, 1.0f, 0.5f, 1.0f }, TRI1_ADJ_COLOR }, /* 5 */ { { 0.6f, 0.33f, 0.5f, 1.0f }, TRI0_ADJ_COLOR }, /* 6 */ { { 1.0f, -0.33f, 0.5f, 1.0f }, TRI1_ADJ_COLOR } /* 7 */ }; static bool SetupVertexBuffer(UINT vertexCount, const Vertex* pVertices, ID3D10Buffer* &pVertexBuffer) { D3D10_BUFFER_DESC vertexBufferDesc = { vertexCount * sizeof(Vertex), D3D10_USAGE_DYNAMIC, D3D10_BIND_VERTEX_BUFFER, D3D10_CPU_ACCESS_WRITE, 0 }; HRESULT hr = pD3D10Device->CreateBuffer(&vertexBufferDesc, NULL, &pVertexBuffer); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create VertexBuffer", NULL, MB_ICONERROR); return false; } Vertex* verts; hr = pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**)&verts); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to map VertexBuffer", NULL, MB_ICONERROR); return false; } memcpy(verts, pVertices, vertexCount * sizeof(Vertex)); pVertexBuffer->Unmap(); return true; } static void Cleanup() { pVertexLayout->Release(); pVertexBufferTadj->Release(); pPixelShader->Release(); pGeometryShader->Release(); pVertexShader->Release(); pVSBuffer->Release(); pRenderTargetView->Release(); pSwapChain->Release(); pD3D10Device->Release(); } static void Render() { float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; pD3D10Device->ClearRenderTargetView(pRenderTargetView, clearColor); UINT stride = sizeof(Vertex); UINT offset = 0; pD3D10Device->IASetInputLayout(pVertexLayout); pD3D10Device->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ); pD3D10Device->VSSetShader(pVertexShader); pD3D10Device->GSSetShader(pGeometryShader); pD3D10Device->PSSetShader(pPixelShader); pD3D10Device->IASetVertexBuffers(0, 1, &pVertexBufferTadj, &stride, &offset); pD3D10Device->Draw(8, 0); pSwapChain->Present(0, 0); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow) { RECT rc; rc.top = 0; rc.left = 0; rc.bottom = WINDOW_HEIGHT; rc.right = WINDOW_WIDTH; AdjustWindowRectEx(&rc, WINDOW_STYLE, FALSE, WINDOW_EXSTYLE); WNDCLASS wc; memset(&wc, 0, sizeof wc); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hInstance = hInstance; wc.lpfnWndProc = WindowProc; wc.lpszClassName = WINDOW_CLASS; wc.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClass(&wc)) { return 1; } hWnd = CreateWindowEx(WINDOW_EXSTYLE, WINDOW_CLASS, WINDOW_TITLE, WINDOW_STYLE, 0, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL); if (hWnd == NULL) { return 1; } HRESULT hr; DXGI_SWAP_CHAIN_DESC scd; memset(&scd, 0, sizeof scd); scd.BufferDesc.Width = WINDOW_WIDTH; scd.BufferDesc.Height = WINDOW_HEIGHT; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferDesc.RefreshRate.Numerator = 60; scd.BufferDesc.RefreshRate.Denominator = 1; scd.SampleDesc.Count = 1; scd.SampleDesc.Quality = 0; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.BufferCount = 1; scd.OutputWindow = hWnd; scd.Windowed = TRUE; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Flags = 0; D3D10_DRIVER_TYPE drivertype = D3D10_DRIVER_TYPE_HARDWARE; if (strncmp(lpCmdLine, "-reference", 10) == 0) { drivertype = D3D10_DRIVER_TYPE_REFERENCE; } hr = D3D10CreateDeviceAndSwapChain(NULL, drivertype, NULL, 0, D3D10_SDK_VERSION, &scd, &pSwapChain, &pD3D10Device); if (FAILED(hr)) { switch (hr) { case D3DERR_INVALIDCALL: MessageBox(hWnd, L"Failed to create D3D10 device D3DERR_INVALIDCALL", NULL, MB_ICONERROR); break; case D3DERR_WASSTILLDRAWING: MessageBox(hWnd, L"Failed to create D3D10 device D3DERR_WASSTILLDRAWING", NULL, MB_ICONERROR); break; case D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS: MessageBox(hWnd, L"Failed to create D3D10 device D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS", NULL, MB_ICONERROR); break; case D3D10_ERROR_FILE_NOT_FOUND: MessageBox(hWnd, L"Failed to create D3D10 device D3D10_ERROR_FILE_NOT_FOUND", NULL, MB_ICONERROR); break; case E_OUTOFMEMORY: MessageBox(hWnd, L"Failed to create D3D10 device E_OUTOFMEMORY", NULL, MB_ICONERROR); break; case E_INVALIDARG: MessageBox(hWnd, L"Failed to create D3D10 device E_INVALIDARG", NULL, MB_ICONERROR); break; default: { WCHAR buffer[64]; wsprintf(buffer, L"Failed to create D3D10 device 0x%X", hr); MessageBox(hWnd, buffer, NULL, MB_ICONERROR); break; } } return 1; } ID3D10Texture2D* pBackBuffer; hr = pSwapChain->GetBuffer(0, IID_ID3D10Texture2D, (void **)&pBackBuffer); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create BackBuffer", NULL, MB_ICONERROR); return 1; } hr = pD3D10Device->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView); pBackBuffer->Release(); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create RenderTargetView", NULL, MB_ICONERROR); return 1; } pD3D10Device->OMSetRenderTargets(1, &pRenderTargetView, NULL); D3D10_VIEWPORT viewport; viewport.Width = WINDOW_WIDTH; viewport.Height = WINDOW_HEIGHT; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0; viewport.TopLeftY = 0; pD3D10Device->RSSetViewports(1, &viewport); LPD3D10BLOB pBuffer = NULL; LPD3D10BLOB pErrors = NULL; hr = D3DX10CompileFromMemory(tadj_vsh, sizeof(tadj_vsh), "tadj.vsh", NULL, NULL, "main", "vs_4_0", 0, 0, NULL, &pBuffer, &pErrors, NULL); if (FAILED(hr)) { char buffer[1024] = ""; if (pErrors) { unsigned int size = pErrors->GetBufferSize(); if (size > sizeof(buffer) - 1) { size = sizeof(buffer) - 1; } memcpy(buffer, pErrors->GetBufferPointer(), size); buffer[size] = '\0'; pErrors->Release(); } MessageBoxA(hWnd, buffer, "Failed to compile VertexShader", MB_ICONERROR); return 1; } hr = pD3D10Device->CreateVertexShader(pBuffer->GetBufferPointer(), pBuffer->GetBufferSize(), &pVertexShader); pVSBuffer = pBuffer; if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create VertexShader", NULL, MB_ICONERROR); return 1; } hr = D3DX10CompileFromMemory(tadj_gsh, sizeof(tadj_gsh), "tadj.gsh", NULL, NULL, "main", "gs_4_0", 0, 0, NULL, &pBuffer, &pErrors, NULL); if (FAILED(hr)) { char buffer[1024] = ""; if (pErrors) { unsigned int size = pErrors->GetBufferSize(); if (size > sizeof(buffer) - 1) { size = sizeof(buffer) - 1; } memcpy(buffer, pErrors->GetBufferPointer(), size); buffer[size] = '\0'; pErrors->Release(); } MessageBoxA(hWnd, buffer, "Failed to compile GeometryShader", MB_ICONERROR); return 1; } hr = pD3D10Device->CreateGeometryShader(pBuffer->GetBufferPointer(), pBuffer->GetBufferSize(), &pGeometryShader); pBuffer->Release(); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create GeometryShader", NULL, MB_ICONERROR); return 1; } hr = D3DX10CompileFromMemory(tadj_psh, sizeof(tadj_psh), "tadj.psh", NULL, NULL, "main", "ps_4_0", 0, 0, NULL, &pBuffer, NULL, NULL); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to compile PixelShader", NULL, MB_ICONERROR); return 1; } hr = pD3D10Device->CreatePixelShader(pBuffer->GetBufferPointer(), pBuffer->GetBufferSize(), &pPixelShader); pBuffer->Release(); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create PixelShader", NULL, MB_ICONERROR); return 1; } if (!SetupVertexBuffer(10, vTri, pVertexBufferTadj)) { return 1; } D3D10_INPUT_ELEMENT_DESC layout[] = { {"position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"color", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0} }; hr = pD3D10Device->CreateInputLayout(layout, 2, pVSBuffer->GetBufferPointer(), pVSBuffer->GetBufferSize(), &pVertexLayout); if (FAILED(hr)) { MessageBox(hWnd, L"Failed to create InputLayout", NULL, MB_ICONERROR); return 1; } ShowWindow(hWnd, SW_SHOW); MSG msg; while (GetMessage(&msg, 0, 0, NULL)) { TranslateMessage(&msg); DispatchMessage(&msg); } Cleanup(); return 0; }
<<attachment: tristripadj6.png>>
<<attachment: tristripadj8.png>>
<<attachment: tristripadj10.png>>
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev