DirectX là một tập hợp thư viện các hàm API được Microsoft thiết kế để cung cấp cho những người phát triển game một giao diện lập trình cấp thấp để liên kết tới các phần cứng của PC chạy trên hệ điều hành Windows.
Trang 1Học viện an ninh nhân dân
BÀI TẬP LỚN MÔN KỸ THUẬT ĐỒ HỌA
Đề tài: DirectX
Nhóm 9
NGUYỄN VIẾT TÙNGNGUYỄN HỮU DƯƠNGTrung đội: B15D45
Giáo viên giảng dạy: Cô HÀ THỊ KIM DUNG
HÀ ĐÔNG-HÀ NỘI 2016
Trang 2MỤC LỤC
I.Giới thiệu về DirectX 2
1 DirectX là gì? 2
2 Sự ra đời và phát triển của DirectX 3
II.Những thành phần cơ bản của DirectX 9
1 Những thành phần cơ bản của các phiên bản DirectX 9.0.(c) 9
2 Những thành phần cơ bản hiện có trong DirectX 11 10
III.Mô hình đối tượng thành phần (COM) 10
IV.Ưu điểm của DirectX (Phiên bản DirectX 11) 11
1 Công nghệ đường ống DirectX 11 11
2 Công nghệ phủ (Tessellation) 12
3 Công nghệ phủ có cả trong Hull Shader và Domain Shader 14
4 Bộ đổ bóng Compute Shader 16
5 Hỗ trợ đa luồng 17
6 Liên kết đổ bóng động (Dynamic Shader Linkage) 17
7 Cải thiện nén kết cấu (Texture Compression) 18
V Ví dụ mô phỏng 20
1 Xây dựng thư viện DDSTextureLoader.h 20
2 Xây dựng thư viện Resource.h 23
Trang 3HỌC VIỆN AN NINH NHÂN DÂN C500
I.Giới thiệu về DirectX
Thuở ban đầu, tên gọi của tất cả các API nay đều được bắt đầu bởi tiền tố Direct, ví dụ
như Direct3D, DirectDraw, DirectMusic, DirectPlay, DirectSound …Tên gọi DirectX đôi khi
được rút gọn chỉ còn X Khi Microsoft tiến hành phát triển một hệ máy chơi game mới, kí tự
X được dùng trong từ Xbox để ám chỉ việc thế hệ máy chơi game này được xây dựng trên
những công nghệ của DirectX Kí tự X sau đó được dùng để đặt tên cho những API được thiết kế dành riêng cho Xbox như XInput, XACT (Audio Creation Tool) … trong khi tiền tố
Trang 4Direct được Microsoft sử dụng để đặt tên cho các API dành cho Windows như Direct2D, DirectWrite …
Mỗi một đối tượng API của DirectX cung cấp một khả năng truy cập khác nhau tới từng loại phần cứng của hệ thống, tất cả chúng đều được xây dựng trên một giao diện chuẩn Giao diệnnày cho phép những người phát triển có thể viết những game của họ bằng cách sử dụng tập hợp cách hàm này lại với nhau mà không cần phải quan tâm nhiều tới phần cứng mà nó sẽ được sử dụng
2 Sự ra đời và phát triển của DirectX
Cuối năm 1994, khi Microsoft chuẩn bị công bố hệ điều hành tiếp theo của họ - Windows 95 Tạithời điểm đó, 3 nhân viên của Microsoft - Craig Eisler, Alex St John, và Eric Engstrom - lo lắng về việc các lập trình viên có xu hướng đánh giá MS-DOS là nền tảng tốt hơn cho lập trình game, và như vậy sẽ có ít tựa game được phát triển cho Windows 95.
Lý do bởi vì DOS cho phép lập trình viên can thiệp trực tiếp vào các thành phần của hệ thống như: video cards, bàm phím, chuột, thiết bị xuất âm thanh … Trong khi đó, Windows 95 với kiến trúc chặt chẽ hơn, không cho phép điều này xảy ra Trong khi chưa đầy 1 tháng nữa Windows 95 sẽ ra mắt, Microsoft cần một chìa khóa để giải quyết mâu thuẫn này Eisler (development lead), St John, và Engstrom (program manager) đã làm việc với nhau, đề xuất một giải pháp mà họ đặt tên là DirectX.
Phiên bản đầu tiên của DirectX phát hành vào tháng 9 năm 1995 với tên gọi Windows Games SDK – cũng là sự thay thế cho DCI và WinG API trên Windows 3.1 Nhờ có DirectX (được tích
hợp vào trong Windows 95 trở về sau), ứng dụng có thể tận dụng sức mạnh phần cứng để xử lý nhiều tác vụ đa phương tiện Eisler có đề cập tới sự “điên cuồng” trong việc xây dựng DirectX1 tới 5 trên blog của anh ta.
Craig Eisler
3
Trang 5HỌC VIỆN AN NINH NHÂN DÂN C500
Alex St John
Eric Engstrom
Việc chuyển dịch sang DirectX khởi đầu khá chậm chạp vì những lo ngại về sự thay thế của WinG, hiệu năng của DirectX – do Windows thời điểm này được xây dựng trên nền DOS và sự ra đi của nhiều lập trình viên DOS.
DirectX 2.0 trở thành một thành phần của Windows trong phiên bản Windows 95
OSR2 và Windows NT 4.0 vào giữa năm 1996 Do Windows 95 còn quá mới mẻ lúc này nên
có rất ít tựa game được phát hành cho nó Microsoft đã triển khai những chiến dịch quảng bá mạnh mẽ cho DirectX nhằm đánh tan sự hoài nghi của giới lập trình viên về nền tảng này Tại
sự kiện Computer Game Developers Conference năm 1996, Microsoft lần đầu tiên giới
thiệu Direct3D và DirectPlay song song với việc minh họa chế độ chơi mạng của
game MechWarrior 2.
Thách thức đặt ra cho nhóm phát triển DirectX là làm thế nào DirectX có thể tương thích với nhiều phần cứng khác nhau Những phần cứng có thể kể đến như những loại card đồ họa, cardâm thanh, motherboard, CPU, thiết bị nhập, xuất … Tất cả các phiên bản DirectX được phát hành đều phải được kiểm tra (ở cả bản beta và bản cuối cùng) một cách kỹ càng để đảm bảo tương thích tốt với phần cứng / phần mềm Ngoài ra, nhóm phát triển cũng gửi những bản mẫu đến các đối tác để chắc chắn phiên bản sắp phát hành tương thích với những phần cứng mới này.
Trang 6Trước DirectX, OpenGL là một thành phần của Windows NT OpenGL tại thời gian này yêu cầu phần cứng cao hơn và tập trung vào các giải pháp kỹ thuật, CAD Direct3D được Microsoft địnhhướng là thành phần gọn nhẹ hơn OpenGL và tập trung chủ yếu vào game Khi các game 3D bắt đầu bùng nổ, OpenGL cũng được phát triển để hỗ trợ tốt hơn cho việc lập trình game, và giờ đây lập trình viên được lựa chọn giữa OpenGL hay Direct3D cho ứng dụng của họ Cũng từđây, cuộc chiến không hồi kết giữa OpenGL và Direct3D bắt đầu Nhiều tranh luận được đưa ragiữa việc xây dựng ứng dụng hỗ trợ đa nền tảng với OpenGL hay chỉ hỗ trợ duy nhất Windows với Direct3D.
Trên các hệ máy chơi game – console – được phát hành bởi Microsoft, DirectX được tùy biến lại dưới sự hợp tác của Nvidia – đối tác phần cứng cho 2 hệ máy chơi game Xbox, Xbox360 – và AMD – hệ máy XboxOne.
Năm 2002, Microsoft phát hành DirectX 9, hỗ trợ lập cho việc lập trình vertex và pixel shader – Shader Model 2.0 Phiên bản Direct9.0c với Shader Model 3.0 được phát hành không lâu sau đó, vào tháng 8 năm 2004.
Tháng 4 năm 2005, DirectShow được gỡ khỏi DirectX và chuyển qua tích hợp vào Microsoft Platform SDK.
Bảng tổng hợp dưới đây liệt kê toàn bộ các phiên bản DirectX, thời điểm ra mắt và các sự kiện liên quan.
5
Trang 7HỌC VIỆN AN NINH NHÂN DÂN C500
(Còn nữa)
DirectX 4 chưa bao giờ được phát hành Raymond Chen – trưởng bộ phận thiết kế phần mềm
của Microsoft – giải thích trong cuốn sách "The Old New Thing" của ông về sự kiện này Sau khiDirectX 3 phát hành, Microsoft tiến hành phát triển phiên bản DirectX 4 và 5 song song với nhau Trong đó, DirectX 4 dự định sẽ là một bản cập nhật một số tính năng, trong khi DirectX 5 dự định sẽ là một phiên bản lớn với nhiều cải tiến Tuy nhiên, lập trình viên tỏ ra không hào hứng với những tính năng sẽ được giới thiệu trong DirectX 4 dẫn tới việc phiên bản này bị "xếp xó" và những tài liệu liên quan tới việc phân biệt 2 phiên bản này cũng bị Microsoft loại bỏ.
Trang 87
Trang 9HỌC VIỆN AN NINH NHÂN DÂN C500
Có thể nói, sự ra đời của DirectX đã lặp lại trật tự cho thế giới đồ họa máy tính và ngành công nghiệp game nói riêng, vốn dĩ trước đây thuộc về OpenGL và rộng cửa cho lập trình viên có thểcó lựa chọn cho riêng mình Ví dụ như các ứng dụng cần chạy trên nhiều nền tảng khác nhau, đặc biệt là các ứng dụng liên quan tới thiết kế sẽ ưu tiên chọn OpenGL và ngược lại, những ứng dụng muốn tối ưu cho Windows, tận dụng các thành phần xây dựng sẵn như xử lý âm thanh, nhập xuất thì có thể lựa chọn DirectX.
Trang 10II.Những thành phần cơ bản của DirectX
1 Những thành phần cơ bản của các phiên bản DirectX 9.0.(c)
Dưới đây là những thành phần cơ bản của DirectX từ phiên bản 9.0(c) trở về các phiênbản trước đó đã bị gỡ bỏ ra khỏi DirectX SDK:
DirectX Graphic: Thành phần này đảm nhiệm tất cả các chức năng kết xuất đồ hoạ củahệ thống Nó cung cấp những hàm API để người dùng có thể quản lý quá trình vẽ 2D cũng như 3D.
DirectInput: Tất cả những gì người dùng nhập vào sẽ được quản lý bởi các hàm API trong thành phần này Nó bao gồm khả năng hỗ trợ các thiết bị như bàn phím, chuột, gamepad, joystick
DirectPlay: Khả năng kết nối mạng được cung cấp cho những hệ thống game của bạn thông qua thành phần DirectPlay này Những hàm phục vụ kết nối này đem đến cho bạn khả năng phát triển ứng dụng có thể giao tiếp với bất kỳ một máy nào khác, cho phép không chỉ một người có thể chơi game đó DirectPlay đem đến cho bạn một giao diện lập trình cấp cao nhằm giúp bạn tránh khỏi những vấn đề khó khăn trong quá trình lập trình ứng dụng liên kết mạng
DirectSound: Chức năng của DirectSound là cho phép bạn có thể tải và chơi một hoặc nhiều file nhạc dạng WAV cũng như toàn bộ khả năng điều khiển quá trình chơi nhạc đó Nếu bạn muốn chèn thêm các hiệu ứng âm thanh hoặc nhạc nền, bạn sẽ cần phải sử dụng tới những hàm API do thành phần này cung cấp
DirectMusic: Nó có khả năng hỗ trợ hầu hết các chức năng chính của một phần mềm chơi nhạc midi như tự chạy lại theo một qui trình đã xác lập, biến đổi âm lượng để phù hợp với hoạt cảnh trong game, thay đổi nhịp của giai điệu và nhiều chức năng cao cấp khác.
DirectShow: Bạn có thể cắt một hoạt cảnh phim hoặc lồng ghép âm thanh và game củamình thông qua thành phần này DirectShow hỗ trợ rất nhiều định dạng file như: AVI, MP3, MPEG , ANF, v.v Với DirectShow, bạn sẽ không phải tải tất cả các đối tượng file này lên bộ nhớ, thay vào đó là truy cập trực tiếp dữ liệu trên ổ cứng hoặc CD-ROM
2 Những thành phần cơ bản hiện có trong DirectX 119
Trang 11HỌC VIỆN AN NINH NHÂN DÂN C500
Direct2D: được sử dụng cho đồ họa 2D trong các ứng dụng Win32 Nó có khả năng dựng hình đồ họa vector với hiệu suất cao.
DirectWrite : được sử dụng để tạo các phông chữ và vẽ chữ trong một ứng dụng Direct2D.
DXGI (DirectX Graphics Infrastructure): tạo ra các chuỗi trao đổi Direct3D và liệt kê các bộ chuyển đổi thiết bị.
Direct3D: được sử dụng cho tất cả các công việc về đồ họa 3D trong DirectX Đây cũng là bộ API mà nhận được nhiều sự chú ý và được cập nhật thường xuyên nhất. XAudio2: là bộ API xử lý âm thanh ở mức độ thấp, đây là 1 phần của XDK (Xbox
Development Kit), và hiện nay là DirectX XDK XAudio2 là sự thay thế DirectSound Các nhà phát triển sẽ sử dụng XAudio 2 nếu họ cần tạo các âm thanh hệ thống ở mức độ thấp.
XACT3 (Microsoft Cross-Platform Audio Creation Tool 3): là bộ API xử lý âm thanh cao cấp hơn được xây dựng dựa trên XAudio2 XACT3 cho phép các nhà phát triển ứng dụng sử dụng Cross-Platform Audio Creation Tool để tạo ra những âm thanh ở trong các ứng dụng của họ Đây là một công cụ mạnh mẽ để tạo ra hệ thống âm thanh trong các trò trơi.
XInput: là bộ API đầu vào cho XDK và Direct X SDK để xử lý đầu vào tất cả các thiếtbị điều khiển của Xbox 360 Về cơ bản, các thiết bị điều khiển có thể sử dụng cho Xbox 360 thì cũng có thể sử dụng trên PC và XInput là bộ API làm việc với các thiết bị này XInput là sự thay thế cho DirectInput.
XNA Math: XNA Math không phải là một bộ API mà là một thư viện toán học tối ưu hóa hoạt động toán học thông thường đối với video games XNA Math sử dụng SIMD (Single Instruction Multi Data) để thực hiện nhiều hoạt động bằng việc gọi một lệnh duy nhất Thư viện XNA Math có sẵn cho Xbox 360 và Windows PC.
DirectCompute: là một bộ API mới được thêm vào DirectX 11 cho phép tính toán đa luồng trong GPU GPU có khả năng xử lý nhiều nhiệm vụ song song ở mức độ vật lý như: nén và giải nén video, xử lý âm thanh, và còn nhiều hơn nữa.
DirectSetup: Sau khi game của bạn đã hoàn thành, bạn sẽ muốn phát hành nó
DirectSetup cung cấp cho bạn những chức năng giúp ứng dụng có thể tự động cài đặt những phiên bản DirectX mới nhất lên hệ thống của người sử dụng
III.Mô hình đối tượng thành phần (COM)
Các hàm DirectX API được thiết kế trên nền tảng Component Object Model (COM) Đối tượng COM bao gồm tập hợp các giao diện nhằm cung cấp các phương thức cho những người lập trình có thể truy cập DirectX Đối tương COM có thể hiểu nôm na là các tệp tin DLL đã được đăng ký với hệ thống Đối với những đối tượng DirectX COM, quá trình này xảy ra khi DirectX được cài đặt vào hệ thống Mặc dù nó khá giống với các đối tượng C++, nhưng các đối tượng COM cần thiết phải có một giao diện để truy cập tới các phương thức bên trong nó Đây thực sự là một thuận lợi so với cách sử dụng các đối tượng thông thường
Trang 12bởi vì ta có thể xây dựng rất nhiều kiểu giao diện cho một đối tượng COM, nó rất thuận lợi cho việc tương thích ngược (hỗ trợ các ứng dụng đã xây dựng trước đó)
Điều này được thể hiện ở việc, mỗi một phiên bản của DirectX đều chứa những giao diện mớicủa DirectDraw và nó có thể truy cập thông qua các hàm API, ngoài ra nó vẫn chứa phiên bảntrước đó nên nó không hề tác động tới những mã lệnh đã được viết trước đó Những game được viết để sử dụng Direct7 hoàn toàn có thể hoạt động với Direct9 hay Direct11 mà không gặp bất kỳ vấn đề gì.
Thêm một lợi điểm nữa của kỹ thuật này là các đối tượng COM có khả năng hoạt động với rấtnhiều ngôn ngữ khác chứ không phải chỉ bằng C++ Người lập trình có thể sử dụng Visual Basic, C++ hay C# mà vẫn có thể sử dụng cùng một thư viện DirectX.
IV.Ưu điểm của DirectX (Phiên bản DirectX 11)
1 Công nghệ đường ống DirectX 11
Điều quan trọng của API mới là khả năng chỉnh sửa nội dung, cho phép các nhà phát triển tạonhiều đối tượng phức tạp hơn và mang tính thực tế cao Điều này phù hợp với sự thúc đẩy củaMicrosoft trong việc cải thiện đa hướng và hiệu năng, do khuynh hướng hiện tại là xây dựngđối tượng nhờ tăng độ phức tạp của các lưới tam giác và sau đó, giảm bớt số tam giác tùytheo sức mạnh của hệ thống cụ thể.
Để giải quyết vấn đề này triệt để, Microsoft giới thiệu 3lớp mới trong công nghệ đường ống (pipeline) DirectX 11: Đổ bóng bề mặt (Hull Shader),công cụ phủ Tessellator và đổ bóng vùng (Domain Shader) Trong đó, đổ bóng bề mặt và đổbóng vùng cũng bao gồm cả quá trình phủ Tessellator Nếu bạn bỏ đi những công đoạn này,bạn sẽ có cấu trúc đường ống của DirectX 10, mặc dù có vài đặc điểm nhỏ khác làm chochúng khác nhau về kỹ thuật.
11
Trang 13HỌC VIỆN AN NINH NHÂN DÂN C500
Hình 1 Cấu tạo đường ống của Direct3D 11
Bổ sung vào 3 lớp trên, quá trình đổ bóng điểm trong cấu trúc đường ống đã có vài thay đổi,cho phép tính toán đổ bóng (Compute Shader - CS) nhiều tác vụ đa năng Theo ý kiến của cácnhà phát triển game và ứng dụng, CS có nhiều cách sử dụng Chỉ cần có một cách phân luồngcho một ứng dụng, thì sẽ có một cách dùng cho CS (Xem hình 1)
2 Công nghệ phủ (Tessellation)
Công nghệ phủ đã xuất hiện ngay từ khi Microsoft công bố Xbox 360 vào cuối năm 2005 –khi Xenos GPU của ATI đã có đơn vị phủ phần cứng chuyên dụng Việc bổ sung này nhằmcải thiện quá trình chỉnh sửa nội dung và cho phép các nhà phát triển cũng như chuyên gia đồhọa sáng tạo nhiều đối tượng thực tế hơn và phức tạp hơn mà không cần bộ nhớ đồ họa quálớn.
Về cơ bản, một đối tượng khi ở xa sẽ ít chi tiết và ít các hình tam giác, nhưng khi tiến lại gầnngười xem thì số lượng tam giác và chi tiết sẽ tăng theo hàm mũ Hình ảnh đẹp chỉ khi nóxuất toàn bộ, tổng số tam giác trung bình phải lớn hơn hằng số cho phép thì sẽ ít xuất hiệnhiện tượng dừng hình, nhảy hình trong lúc hiển thị.
Trang 14Hình 2 Tạo đối tượng với cấu trúc đường ống hiện tại
Theo truyền thống, việc tạo đối tượng bắt đầu từ mô hình khung Sub-D, đến hoạt cảnh và ánhxạ phủ bề mặt trước khi một lưới đa giác áp dụng nó Một khi lưới đã được áp dụng, nó đượcchia lại nhiều cấp bậc chi tiết (LOD – Level Of Detail) trước khi được gửi đến GPU Các cấpbậc khác nhau có thể được sử dụng cho những lớp khác nhau của phần cứng hoặc chúng cóthể được dùng khi nhân vật hay đối tượng của nội dung xa màn hình, bổ sung nhiều chi tiếthơn cho người xem, nhưng tốn càng ít “công sức” càng tốt (Xem hình 2)
Microsoft và AMD cho rằng Tessellator của Xbox 360 và cả Radeon HD 2000/3000/4000đều không tương thích với DirectX 11, nhưng Tessellator của DirectX 11 có thể tương thíchvới tất cả các phần cứng khác đang có mặt trên thị trường Tuy nhiên, một điểm tiến bộ làcông cụ phủ của Radeon HD 4000 đã có vài thay đổi, cho phép lập trình viên truy xuất vàotính năng trong ứng dụng của DirectX 10 – Điều này là một bước phát triển so với đơn vị phủtrong của GPU dòng HD 2000 và 3000.
Mặc dù các nhà phát triển không thích dùng Tessellator cho các ứng dụng ra đời ngày nay,công nghệ phủ của RV7xx đã tỏ ra là một nền tảng hữu dụng vì nó cho phép các nhà pháttriển và chuyên gia đồ họa làm thí nghiệm với công nghệ phủ trong một môi trường lập trình
13
Trang 15HỌC VIỆN AN NINH NHÂN DÂN C500
khá giống DirectX 11 Nói tóm lại, công nghệ đường ống đồ họa DirectX 11 là một tập hợpmẹ của DirectX 10 mà sự bổ sung chủ yếu là công nghệ phủ.
Hình 3 Hull Shader trong tiến trình
Tuy công cụ phủ DirectX 11 mạnh mẽ và linh hoạt hơn các thành phần phủ của GPU AMDgần đây (bao gồm cả Xenos) Nhưng thật sự, Tessellator vẫn không thể lập trình được mà chỉdựa vào thành phần Hull Shader (đổ bóng bề mặt) để được cung cấp thông tin phù hợp và sauđó, Domain Shader nhận dữ liệu phủ và xuất ra các đỉnh trước khi nó chuyển xuống các phầntiếp theo của cấu trúc đường ống.
3 Công nghệ phủ có cả trong Hull Shader và Domain Shader
Hull Shader là nơi tiến trình phủ một đối tượng được thiết lập – nó điều khiển các điểm củamảng rồi sau đó tính toán cấp độ phủ yêu cầu Sau bước chuyển đổi cơ bản, các điểm điềukhiển sẽ được chuyển vào Domain Shader – bộ phận phủ không thấy được các điểm điềukhiển.
Thay vào đó, công cụ phủ Tessellator được cung cấp một số TessFactor, về cơ bản sẽ cho biếtcấp độ phủ được yêu cầu trên một miếng khảm cụ thể Hull Shader cũng báo cho bộ phận phủphương thức (mode) mà nó nên thực hiện – nhà phát triển có thể định rõ cách mà tiến trìnhphủ thực hiện công việc (mặc dù đơn vị phủ là tính năng cố định, nhưng có vài phương thứcđể lựa chọn)
Trang 16Sau đó, Tessellator nhận những gì được cung cấp bởi Hull Shader rồi kết hợp các mảng đểtạo yêu cầu hình học bổ sung Khi quá trình này hoàn thành, các điểm vùng (domain point) vàdữ liệu hình học sẽ xuất hiện. (Xem các hình 3, 4,5)
Hình 4 Hoạt động của công cụ phủ cố định Tessellator
15
Trang 17HỌC VIỆN AN NINH NHÂN DÂN C500
Hình 5 Hoạt động của Domain Shader
Các điểm vùng được chuyển xuống Domain Shader (làm việc trên từng điểm cơ bản), khi đóbộ phận này sẽ nhận điểm vùng và tạo đỉnh cho các giai đoạn tiếp theo Trong khi đó, dữ liệuhình học đi thẳng xuống lớp gốc của đường ống – lý do là dữ liệu này không cần đổ bóng,nhưng lại cần chuyển đổi (Xem hình 6)
Điều quan trọng ở đây là cả lớp phủ của đường ống không làm việc với các tam giác mà chỉlàm việc với các miếng khảm và điểm Các miếng khảm sẽ mô tả đường cong hoặc vùng bềmặt bởi 4 cạnh Tất nhiên, các mảng có thể được mô tả với những tam giác, nhưng điều đókhông phổ biến, vì hầu hết các ứng dụng chỉnh sửa 3D đều làm việc với 4 cạnh Đây là lầnđầu tiên DirectX không làm việc với tam giác, đó là một bước tiến đáng kể.
Tất cả những đặc điểm mô tả trên là bước tiến rõ rệt trong công nghệ đường ống của DirectX11, hứa hẹn sẽ mang đến hiệu quả không ngờ khi bổ sung thật nhiều chi tiết cho công nghệgame tương lai Tất nhiên, các nhà phát triển không phải sử dụng lớp này của đường ống nếuhọ không muốn.
4 Bộ đổ bóng Compute Shader
Trang 18Compute Shader sẽ nhận dữ liệu từ Pixel Shader Bộ đổ bóng tính toán mới này hỗ trợ tốt hơncho nhiều hãng phần cứng khác nhau, gia tăng khả năng lập trình cho các GPU đa năng(GPGPU – General Purpose GPU) mà NVIDIA và AMD đang tích cực cải tiến trong nhữngnăm gần đây Nhờ cải tiến Compute Shader, ngoài việc dựng hình, các GPU giờ đây thựchiện cả những tính toán khác, chẳng hạn như tạo hiệu ứng bóng mờ.
Microsoft cho rằng các nhà phát triển sẽ cảm thấy dễ dàng hơn trong việc phát triển các ứngdụng game trong khi các phần cứng được tận dụng hết khả năng Dự kiến, bộ phát triển phầnmềm (Software Development Kit) sẽ được Microsoft phát hành trong thời gian tới.
5 Hỗ trợ đa luồng
Mặc dù kỹ thuật đa luồng (multi-threading) không còn mới trong công nghệ đường ống đồhọa nhưng đây là tính năng quan trọng cho DirectX 11 Thậm chí, nó trở nên quan trọng hơnkhi sử dụng phần cứng DirectX10 cũng như cập nhật trình điều khiển (driver).
CPU 2 nhân là xu thế hiện nay và 4 nhân bây giờ không còn là lựa chọn quá đắt cho game thủhay những chuyên gia đồ họa; trong tương lai, 4 nhân sẽ thay thế 2 nhân như một xu thế tấtyếu Điều đáng ngạc nhiên là DirectX vẫn chưa thể xử lý đa luồng Để “che đậy’” thiếu sótnày, cả AMD và NVIDIA đưa ra các trình điều khiển đa luồng, nhưng thành công còn hạnchế vì bản chất API là đơn luồng API của DirectX 11 đem lại cho lập trình viên khả năngđiều khiển GPU từ CPU đa nhân Những thay đổi trong mô hình API và mô hình trình điềukhiển của DirectX 11 đã cải thiện việc tính toán của CPU Việc truy cập các thiết bị khôngđồng bộ giờ đây đã được thực hiện thông qua hai tính năng chính của đối tượng thiết bị trongthư viện Direct3D 11.
Cách để Microsoft đạt được điều này là tách một thiết bị Direct3D thành 3 giao diện riêngbiệt: giao diện ngữ cảnh thiết bị (Device Context), giao diện ngữ cảnh trực tiếp (ImmediateContext) và giao diện ngữ cảnh trì hoãn (Deferred Context) Immediate Context có một luồngtrong khi giao diện Device Context và Deferred Context thì có nhiều luồng hơn, được chỉđịnh xếp hàng các tác vụ cho Immediate Context hoặc Render.
Mỗi giao diện thiết bị có thể tải luồng tài nguyên khi và chỉ khi nó cần, trong khi giao diệnngữ cảnh trì hoãn (Deferred Context interface) hoạt động như một ngữ cảnh thiết bị đơnluồng cho các toán tử dựng hình tương lai, nó xếp hàng các lệnh gọi (hoặc Display Lists)trước khi chuyển chúng vào giao diện ngữ cảnh trực tiếp.
Khi muốn tối ưu hoá phần cứng hỗ trợ DirectX 10, giao diện ngữ cảnh trì hoãn sẽ cần lậptrình trên phần mềm thay vì phần cứng Vì thế, giao diện ngữ cảnh trì hoãn sẽ không đượcchia luồng tự do trên phần cứng DirectX 10 và một luồng chuyên dụng sẽ phải được chỉ địnhđến ngữ cảnh trì hoãn ở cấp độ API.
6 Liên kết đổ bóng động (Dynamic Shader Linkage)
Một trong những vấn đề mà các nhà lập trình game đối mặt hiện nay là sự mở rộng và tínhlinh hoạt đổ bóng quá phức tạp Ví dụ, nếu trong vài trường hợp cần nhiều shader thì một
17
Trang 19HỌC VIỆN AN NINH NHÂN DÂN C500
Uber Shader lớn thường được dùng vì nó kết nối được tất cả các shader cần thiết vào trongmột đoạn mã (code), tối giản lập trình.
Hình 6 Tạo đối tượng với cấu trúc đường ống mới
Tuy nhiên, việc tối giản lập trình theo hướng này lại làm cho việc đổ bóng phức tạp vô cùng,nó không chỉ kém hiệu quả hơn các shader riêng lẻ mà còn khó bẫy lỗi Giải pháp viết cácshader chuyên dụng không những phù hợp cho tất cả các trường hợp mà còn phù hợp cho cáclớp khác nhau của phần cứng Giải pháp này lại trở nên phức tạp và tốn nhiều chi phí liênquan đến việc chuyển đổi các shader, vì vậy Uber shader là một tuỳ chọn dễ dàng nhất chonhà lập trình trong viết mã dù chưa phải lý tưởng.
Microsoft tin rằng câu trả lời cho vấn đề này là các thủ tục con (subroutine), cho phép các nhàlập trình liên kết các shader với nhau, các nhà lập trình có thể tạo các shader chuyên dụng chocác lớp khác nhau của phần cứng được chỉ định, trong khi đó lại giảm phần lớn việc sử dụngthanh ghi so với việc dùng một shader đơn lẻ để điều khiển tất cả Hi vọng rằng, điều này làmcho các nhà lập trình có hứng thú hơn khi viết shader, nhưng không có nghĩa là sẽ ảnh hưởngtrực tiếp đến chất lượng hình ảnh mà cụ thể là chất lượng đổ bóng.
7 Cải thiện nén kết cấu (Texture Compression)
Trang 20Đã lâu kể từ khi Microsoft nâng cấp thuật toán nén kết cấu của DirectX, giờ đây Microsoftlưu ý đến những thiếu sót của việc hỗ trợ cho các định dạng kết cấu HDR (High DynamicRange), khi đa kết cấu không chú ý đến giải pháp nén gốc.
Để bổ sung những gì cần thiết, Direct3D 11 sẽ giới thiệu 2 định dạng kết cấu mới là BC6(hay BC6H) và BC7 BC6 là một kết cấu định dạng cao nhưng chỉ tiếc là mất dữ liệu gốc khinén, thay vào đó, nó hỗ trợ công nghệ nén 6:1 với tốc độ 16bpc (bits per channel), điều nàymang lại hiệu quả nhưng chất lượng kết cấu chưa cao trong trường hợp sử dụng mở rộng dảisáng có độ nhạy cao (high-dynamic) và không thật sự còn nguyên gốc.
Bên cạnh đó, BC7 là một định dạng kết cấu LDR (Low Dynamic Range), hỗ trợ tỷ lệ nén 3:1RGB BC7 có thể được sử dụng với chất lượng giảm nhẹ (4:1 và 3:1 như đã nói ở trên) nhưngvẫn đảm bảo ở mức cao.
Hơn nữa, Microsoft cho rằng, giải nén kết cấu trong DirectX 11 phải được làm theo cáchhoàn toàn chính xác với thông số kỹ thuật của API thì chất lượng giải nén kết cấu mới tănglên nhiều Cho đến khi DirectX 11 xuất hiện, vẫn còn thời gian cho các hãng cung cấp phầncứng điều chỉnh cách mà phần cứng hỗ trợ DirectX 10 (và các DirectX cũ hơn) điều khiểngiải nén kết cấu.
19
Trang 21HỌC VIỆN AN NINH NHÂN DÂN C500
V.Ví dụ mô phỏng
1 Xây dựng thư viện DDSTextureLoader.h
// File: DDSTextureLoader.h
#ifdef _MSC_VER
// -#pragma once#endif
#if defined(_XBOX_ONE) && defined(_TITLE)#include <d3d11_x.h>
#define DCOMMON_H_INCLUDED#define NO_D3D11_DEBUG_NAME#else
#include <d3d11_1.h>
#pragma warning(push)
#pragma warning(disable : 4005)#include <stdint.h>
#pragma warning(pop)
#if defined(_MSC_VER) && (_MSC_VER<1610) && !defined(_In_reads_)#define _In_reads_(exp)
#define _Out_writes_(exp)#define _In_reads_bytes_(exp)#define _In_reads_opt_(exp)#define _Outptr_opt_
#endif
Trang 22#ifndef _Use_decl_annotations_
#define _Use_decl_annotations_#endif
namespace DirectX{
enum DDS_ALPHA_MODE
{
DDS_ALPHA_MODE_UNKNOWN = 0, DDS_ALPHA_MODE_STRAIGHT = 1, DDS_ALPHA_MODE_PREMULTIPLIED = 2, DDS_ALPHA_MODE_OPAQUE = 3, DDS_ALPHA_MODE_CUSTOM = 4, };
// Standard version
HRESULT CreateDDSTextureFromMemory( _In_ID3D11Device* d3dDevice, _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, _In_size_t ddsDataSize,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _In_size_t maxsize = 0,
_Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
HRESULT CreateDDSTextureFromFile( _In_ID3D11Device* d3dDevice, _In_z_ const wchar_t* szFileName,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _In_size_t maxsize = 0,
_Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
// Standard version with optional auto-gen mipmap support
HRESULT CreateDDSTextureFromMemory( _In_ID3D11Device* d3dDevice, _In_opt_ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, _In_size_t ddsDataSize,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _In_size_t maxsize = 0,
_Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
21
Trang 23HỌC VIỆN AN NINH NHÂN DÂN C500
HRESULT CreateDDSTextureFromFile( _In_ID3D11Device* d3dDevice, _In_opt_ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _In_size_t maxsize = 0,
_Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
// Extended version
HRESULT CreateDDSTextureFromMemoryEx( _In_ID3D11Device* d3dDevice, _In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, _In_size_t ddsDataSize,
_In_size_t maxsize,
_In_D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
HRESULT CreateDDSTextureFromFileEx( _In_ID3D11Device* d3dDevice, _In_z_ const wchar_t* szFileName,
_In_size_t maxsize,
_In_D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
// Extended version with optional auto-gen mipmap support
HRESULT CreateDDSTextureFromMemoryEx( _In_ID3D11Device* d3dDevice, _In_opt_ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData, _In_size_t ddsDataSize,
_In_size_t maxsize,
_In_D3D11_USAGE usage,
Trang 24_In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
HRESULT CreateDDSTextureFromFileEx( _In_ID3D11Device* d3dDevice, _In_opt_ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName, _In_size_t maxsize,
_In_D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
_Outptr_opt_ID3D11Resource** texture,
_Outptr_opt_ID3D11ShaderResourceView** textureView, _Out_opt_DDS_ALPHA_MODE* alphaMode = nullptr );
Trang 25HỌC VIỆN AN NINH NHÂN DÂN C500
4 Xây dựng DDSTextureLoader.cpp
// File: DDSTextureLoader.cpp
#include <assert.h>
// -#include <algorithm>
Trang 26#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))#endif /* defined(MAKEFOURCC) */
// DDS file structure definitions
// See DDS.h in the 'Texconv' sample and the 'DirectXTex' library// -#pragma pack(push,1)
const uint32_t DDS_MAGIC = 0x20534444; // "DDS "struct DDS_PIXELFORMAT
uint32_t size; uint32_t flags; uint32_t fourCC;
uint32_t RGBBitCount; uint32_t RBitMask; uint32_t GBitMask; uint32_t BBitMask; uint32_t ABitMask;};
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC#define DDS_RGB 0x00000040 // DDPF_RGB
#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
25
Trang 27HỌC VIỆN AN NINH NHÂN DÂN C500
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT
#define DDS_WIDTH 0x00000004 // DDSD_WIDTH
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX |
DDS_CUBEMAP_NEGATIVEX |\
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP
enum DDS_MISC_FLAGS2
DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,};
struct DDS_HEADER
uint32_t size; uint32_t flags; uint32_t height; uint32_t width;
uint32_t pitchOrLinearSize;
uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags uint32_t mipMapCount;
uint32_t reserved1[11]; DDS_PIXELFORMAT ddspf; uint32_t caps;
uint32_t caps2; uint32_t caps3;
Trang 28uint32_t caps4; uint32_t reserved2;};
struct DDS_HEADER_DXT10
DXGI_FORMAT dxgiFormat; uint32_t resourceDimension;
uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG uint32_t arraySize;
uint32_t miscFlags2;};
#pragma pack(pop)
template<UINT TNameLength>
inline void SetDebugObjectName(_In_ID3D11DeviceChild* resource, _In_ const char (&name)[TNameLength])
#if defined(_DEBUG) || defined(PROFILE)
resource->SetPrivateData(WKPDID_D3DDebugObjectName, TNameLength - 1, name);#else
UNREFERENCED_PARAMETER(resource); UNREFERENCED_PARAMETER(name);#endif
// -static HRESULT LoadTextureDataFromFile( _In_z_ const wchar_t* fileName, std::unique_ptr<uint8_t[]>& ddsData,
DDS_HEADER** header,27
Trang 29HỌC VIỆN AN NINH NHÂN DÂN C500
uint8_t** bitData, size_t* bitSize )
if (!header || !bitData || !bitSize) {
return E_POINTER; }
// open the file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_READ,
FILE_SHARE_READ, OPEN_EXISTING, nullptr ) ) );#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_READ,
FILE_SHARE_READ, nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr ) ) );
#endif if ( !hFile ) {
return HRESULT_FROM_WIN32( GetLastError() ); }
// Get the file size
GetFileSizeEx( hFile.get(), &FileSize );
Trang 30// Need at least enough data to fill the header and magic number to be a valid DDS if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) ) )
{
return E_FAIL; }
// create enough space for the file data
ddsData.reset( new (std::nothrow) uint8_t[ FileSize.LowPart ] ); if (!ddsData)
{
return E_OUTOFMEMORY; }
// read the data in DWORD BytesRead = 0; if (!ReadFile( hFile.get(), ddsData.get(), FileSize.LowPart, &BytesRead, nullptr ))
{
return HRESULT_FROM_WIN32( GetLastError() ); }
if (BytesRead < FileSize.LowPart) {
return E_FAIL; }
// DDS files always start with the same magic number ("DDS ") uint32_t dwMagicNumber = *( const uint32_t* )( ddsData.get() ); if (dwMagicNumber != DDS_MAGIC)
{
return E_FAIL; }
29
Trang 31HỌC VIỆN AN NINH NHÂN DÂN C500
auto hdr = reinterpret_cast<DDS_HEADER*>( ddsData.get() + sizeof( uint32_t ) ); // Verify header to validate DDS file
if (hdr->size != sizeof(DDS_HEADER) ||
hdr->ddspf.size != sizeof(DDS_PIXELFORMAT)) {
return E_FAIL; }
// Check for DX10 extension bool bDXT10Header = false;
if ((hdr->ddspf.flags & DDS_FOURCC) &&
(MAKEFOURCC( 'D', 'X', '1', '0' ) == hdr->ddspf.fourCC)) {
// Must be long enough for both headers and magic value
if (FileSize.LowPart < ( sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10) ) )
{
return E_FAIL; }
bDXT10Header = true; }
// setup the pointers in the process request *header = hdr;
ptrdiff_t offset = sizeof( uint32_t ) + sizeof( DDS_HEADER )
+ (bDXT10Header ? sizeof( DDS_HEADER_DXT10 ) : 0); *bitData = ddsData.get() + offset;
*bitSize = FileSize.LowPart - offset; return S_OK;
// Return the BPP for a particular format
static size_t BitsPerPixel( _In_DXGI_FORMAT fmt )
switch( fmt ) {
case DXGI_FORMAT_R32G32B32A32_TYPELESS: case DXGI_FORMAT_R32G32B32A32_FLOAT: case DXGI_FORMAT_R32G32B32A32_UINT: case DXGI_FORMAT_R32G32B32A32_SINT:
Trang 32return 128;
case DXGI_FORMAT_R32G32B32_TYPELESS: case DXGI_FORMAT_R32G32B32_FLOAT: case DXGI_FORMAT_R32G32B32_UINT: case DXGI_FORMAT_R32G32B32_SINT: return 96;
case DXGI_FORMAT_R16G16B16A16_TYPELESS: case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_R16G16B16A16_UNORM: case DXGI_FORMAT_R16G16B16A16_UINT: case DXGI_FORMAT_R16G16B16A16_SNORM: case DXGI_FORMAT_R16G16B16A16_SINT: case DXGI_FORMAT_R32G32_TYPELESS: case DXGI_FORMAT_R32G32_FLOAT: case DXGI_FORMAT_R32G32_UINT: case DXGI_FORMAT_R32G32_SINT:
case DXGI_FORMAT_R32G8X24_TYPELESS: case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: case DXGI_FORMAT_Y416:
case DXGI_FORMAT_Y210: case DXGI_FORMAT_Y216: return 64;
case DXGI_FORMAT_R10G10B10A2_TYPELESS: case DXGI_FORMAT_R10G10B10A2_UNORM: case DXGI_FORMAT_R10G10B10A2_UINT: case DXGI_FORMAT_R11G11B10_FLOAT: case DXGI_FORMAT_R8G8B8A8_TYPELESS: case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8B8A8_SNORM: case DXGI_FORMAT_R8G8B8A8_SINT: case DXGI_FORMAT_R16G16_TYPELESS: case DXGI_FORMAT_R16G16_FLOAT: case DXGI_FORMAT_R16G16_UNORM: case DXGI_FORMAT_R16G16_UINT: case DXGI_FORMAT_R16G16_SNORM: case DXGI_FORMAT_R16G16_SINT: case DXGI_FORMAT_R32_TYPELESS:
31
Trang 33HỌC VIỆN AN NINH NHÂN DÂN C500 case DXGI_FORMAT_D32_FLOAT: case DXGI_FORMAT_R32_FLOAT: case DXGI_FORMAT_R32_UINT: case DXGI_FORMAT_R32_SINT:
case DXGI_FORMAT_R24G8_TYPELESS: case DXGI_FORMAT_D24_UNORM_S8_UINT: case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: case DXGI_FORMAT_X24_TYPELESS_G8_UINT: case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: case DXGI_FORMAT_R8G8_B8G8_UNORM: case DXGI_FORMAT_G8R8_G8B8_UNORM: case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_B8G8R8X8_UNORM:
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: case DXGI_FORMAT_B8G8R8A8_TYPELESS:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_Y410: case DXGI_FORMAT_YUY2: return 32;
case DXGI_FORMAT_P010: case DXGI_FORMAT_P016: return 24;
case DXGI_FORMAT_R8G8_TYPELESS: case DXGI_FORMAT_R8G8_UNORM: case DXGI_FORMAT_R8G8_UINT: case DXGI_FORMAT_R8G8_SNORM: case DXGI_FORMAT_R8G8_SINT: case DXGI_FORMAT_R16_TYPELESS: case DXGI_FORMAT_R16_FLOAT: case DXGI_FORMAT_D16_UNORM: case DXGI_FORMAT_R16_UNORM: case DXGI_FORMAT_R16_UINT: case DXGI_FORMAT_R16_SNORM: case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_B5G6R5_UNORM: case DXGI_FORMAT_B5G5R5A1_UNORM: case DXGI_FORMAT_A8P8:
case DXGI_FORMAT_B4G4R4A4_UNORM: return 16;
Trang 34case DXGI_FORMAT_NV12:
case DXGI_FORMAT_420_OPAQUE: case DXGI_FORMAT_NV11:
return 12;
case DXGI_FORMAT_R8_TYPELESS: case DXGI_FORMAT_R8_UNORM: case DXGI_FORMAT_R8_UINT: case DXGI_FORMAT_R8_SNORM: case DXGI_FORMAT_R8_SINT: case DXGI_FORMAT_A8_UNORM: case DXGI_FORMAT_AI44:
case DXGI_FORMAT_IA44: case DXGI_FORMAT_P8: return 8;
case DXGI_FORMAT_R1_UNORM: return 1;
case DXGI_FORMAT_BC1_TYPELESS: case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: case DXGI_FORMAT_BC4_TYPELESS: case DXGI_FORMAT_BC4_UNORM: case DXGI_FORMAT_BC4_SNORM: return 4;
case DXGI_FORMAT_BC2_TYPELESS: case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: case DXGI_FORMAT_BC3_TYPELESS: case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: case DXGI_FORMAT_BC5_TYPELESS: case DXGI_FORMAT_BC5_UNORM: case DXGI_FORMAT_BC5_SNORM: case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: return 8;
33
Trang 35HỌC VIỆN AN NINH NHÂN DÂN C500
#if defined(_XBOX_ONE) && defined(_TITLE)
case DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT: case DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT: return 32;
case DXGI_FORMAT_D16_UNORM_S8_UINT: case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: case DXGI_FORMAT_X16_TYPELESS_G8_UINT: return 24;
#endif // _XBOX_ONE && _TITLE default:
return 0; }
// Get surface information for a particular format
static void GetSurfaceInfo( _In_size_t width,
_In_size_t height,
_In_DXGI_FORMAT fmt,
_Out_opt_size_t* outNumBytes, _Out_opt_size_t* outRowBytes, _Out_opt_size_t* outNumRows ){
size_t numBytes = 0; size_t rowBytes = 0; size_t numRows = 0; bool bc = false; bool packed = false; bool planar = false; size_t bpe = 0; switch (fmt) {
case DXGI_FORMAT_BC1_TYPELESS: case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: case DXGI_FORMAT_BC4_TYPELESS: case DXGI_FORMAT_BC4_UNORM: case DXGI_FORMAT_BC4_SNORM:
Trang 36bc=true; bpe = 8; break;
case DXGI_FORMAT_BC2_TYPELESS: case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB: case DXGI_FORMAT_BC3_TYPELESS: case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB: case DXGI_FORMAT_BC5_TYPELESS: case DXGI_FORMAT_BC5_UNORM: case DXGI_FORMAT_BC5_SNORM: case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: case DXGI_FORMAT_BC6H_SF16: case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: bc = true;
bpe = 16; break;
case DXGI_FORMAT_R8G8_B8G8_UNORM: case DXGI_FORMAT_G8R8_G8B8_UNORM: case DXGI_FORMAT_YUY2:
packed = true; bpe = 4;
break;
case DXGI_FORMAT_Y210: case DXGI_FORMAT_Y216: packed = true;
bpe = 8; break;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_420_OPAQUE: planar = true;
bpe = 2; break;
case DXGI_FORMAT_P010: case DXGI_FORMAT_P016:
35
Trang 37HỌC VIỆN AN NINH NHÂN DÂN C500 planar = true;
bpe = 4; break;
#if defined(_XBOX_ONE) && defined(_TITLE) case DXGI_FORMAT_D16_UNORM_S8_UINT: case DXGI_FORMAT_R16_UNORM_X8_TYPELESS: case DXGI_FORMAT_X16_TYPELESS_G8_UINT: planar = true;
bpe = 4; break;#endif } if (bc) {
size_t numBlocksWide = 0; if (width > 0)
{
numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 ); }
size_t numBlocksHigh = 0; if (height > 0)
rowBytes = ( ( width + 1 ) >> 1 ) * bpe; numRows = height;
numBytes = rowBytes * height; }
else if ( fmt == DXGI_FORMAT_NV11 ) {
Trang 38}
else if (planar) {
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
numBytes = ( rowBytes * height ) + ( ( rowBytes * height + 1 ) >> 1 ); numRows = height + ( ( height + 1 ) >> 1 );
} else {
*outNumBytes = numBytes; }
if (outRowBytes) {
*outRowBytes = rowBytes; }
if (outNumRows) {
*outNumRows = numRows; }
// Note that sRGB formats are written using the "DX10" extended header switch (ddpf.RGBBitCount)
{
case 32:
if (ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000)) {
return DXGI_FORMAT_R8G8B8A8_UNORM;37
Trang 39HỌC VIỆN AN NINH NHÂN DÂN C500 }
if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000)) {
return DXGI_FORMAT_B8G8R8A8_UNORM; }
if (ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000)) {
return DXGI_FORMAT_B8G8R8X8_UNORM; }
// No DXGI format maps to
ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) aka D3DFMT_X8B8G8R8 // Note that many common DDS reader/writers (including D3DX) swap the
// the RED/BLUE masks for 10:10:10:2 formats We assumme
// below that the 'backwards' header mask is being used since it is most // likely written by D3DX The more robust solution is to use the 'DX10' // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
// For 'correct' writers, this should be 0x000003ff,0x000ffc00,0x3ff00000 for RGB data
if (ISBITMASK(0x3ff00000,0x000ffc00,0x000003ff,0xc0000000)) {
return DXGI_FORMAT_R10G10B10A2_UNORM; }
// No DXGI format maps to
ISBITMASK(0x000003ff,0x000ffc00,0x3ff00000,0xc0000000) aka D3DFMT_A2R10G10B10
if (ISBITMASK(0x0000ffff,0xffff0000,0x00000000,0x00000000)) {
return DXGI_FORMAT_R16G16_UNORM; }
if (ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000)) {
// Only 32-bit color channel format in D3D9 was R32F
return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114 }
break;
Trang 40return DXGI_FORMAT_B5G5R5A1_UNORM; }
if (ISBITMASK(0xf800,0x07e0,0x001f,0x0000)) {
return DXGI_FORMAT_B5G6R5_UNORM; }
// No DXGI format maps to ISBITMASK(0x7c00,0x03e0,0x001f,0x0000) aka D3DFMT_X1R5G5B5
if (ISBITMASK(0x0f00,0x00f0,0x000f,0xf000)) {
return DXGI_FORMAT_B4G4R4A4_UNORM; }
// No DXGI format maps to ISBITMASK(0x0f00,0x00f0,0x000f,0x0000) aka D3DFMT_X4R4G4B4
// No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc.
break; }
}
else if (ddpf.flags & DDS_LUMINANCE) {
if (8 == ddpf.RGBBitCount) {
if (ISBITMASK(0x000000ff,0x00000000,0x00000000,0x00000000)) {
return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension
}
// No DXGI format maps to ISBITMASK(0x0f,0x00,0x00,0xf0) aka D3DFMT_A4L4 }
39