diff --git a/.gitignore b/.gitignore index 7c06cad..9cd8037 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /build/ /target/ +conformance/*.xml +conformance/*.qpa **/*.rs.bk Cargo.lock diff --git a/Makefile b/Makefile index 62a15e8..0d077ce 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ VULKAN_DIR=modules/vulkan-docs/src +CTS_DIR=../VK-GL-CTS BINDING=target/vulkan.rs NATIVE_DIR=target/native TARGET=$(NATIVE_DIR)/test @@ -31,9 +32,10 @@ else endif endif +FULL_LIBRARY_PATH=$(CURDIR)/target/debug LIBRARY=target/debug/libportability.$(LIB_EXTENSION) -.PHONY: all binding run +.PHONY: all binding run cts all: $(TARGET) @@ -55,6 +57,12 @@ $(TARGET): $(LIBRARY) $(OBJECTS) Makefile run: $(TARGET) $(TARGET) +cts: $(TARGET) + -LD_LIBRARY_PATH=$(FULL_LIBRARY_PATH) $(CTS_DIR)/build/external/vulkancts/modules/vulkan/deqp-vk + python $(CTS_DIR)/scripts/log/log_to_xml.py TestResults.qpa conformance/last.xml + mv TestResults.qpa conformance/last.qpa + firefox conformance/last.xml + clean: rm -f $(OBJECTS) $(TARGET) $(BINDING) cargo clean diff --git a/README.md b/README.md index 2e733c4..f8086ce 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,12 @@ This is a prototype library implementing [Vulkan Portability Initiative](https:/ | gfx-rs Backend | Total cases | Pass | Fail | Quality warning | Compatibility warning | Not supported | Resource error | Internal error | Timeout | Crash | | -------------- | -- | -- | -- | - | - | - | - | - | - | - | -| *Vulkan* | 3576 | 652 | 676 | 0 | 0 | 2248 | 0 | 0 | 0 | 0 | +| *Vulkan* | 3589 | 665 | 676 | 0 | 0 | 2248 | 0 | 0 | 0 | 0 | | *DX12* | 3563 | 1243 | 73 | 0 | 0 | 2247 | 0 | 0 | 0 | 0 | -Currently crashing on "dEQP-VK.api.object_management.single.buffer_view_uniform_r8g8b8a8_unorm". +Currently crashing on event handling. + +Please visit [our wiki](https://github.com/gfx-rs/portability/wiki/Vulkan-CTS-status) for CTS hookup instructions. Once everything is set, you can generate the new results by calling `make cts`. ## Check out ``` diff --git a/conformance/testlog.css b/conformance/testlog.css new file mode 100644 index 0000000..10fe798 --- /dev/null +++ b/conformance/testlog.css @@ -0,0 +1,121 @@ +body +{ + font-size: 10pt; + font-family: verdana; +} + +h1 +{ + font-size: 16pt; + font-weight: normal; + width: 100%; + padding: 4pt 0pt 6pt 0pt; + margin: 0px 0px 10pt 0px; +} + +h2 +{ + font-size: 14pt; + font-weight: normal; + background: #cccccc; + width: 100%; + padding: 2pt 0pt 4pt 0pt; + margin: 0pt 0pt 2pt 0pt; +} + +h3 +{ + font-size: 12pt; + font-weight: normal; + width: 100%; + padding: 2pt 0pt 4pt 0pt; + margin: 0pt 0pt 0pt 0pt; +} + +div.Section +{ + border: 1px solid #aaaaaa; + margin: 2pt 2pt 4pt 10pt; + padding: 0pt; +} + +div.CompileInfo +{ + border: 1px solid #aaaaaa; + margin: 2pt 2pt 4pt 10pt; + padding: 0pt; +} + +div.Shader +{ + border: 1px solid #aaaaaa; + margin: 2pt 2pt 4pt 10pt; + padding: 0pt; +} + +div.ImageSet +{ + border: 1px solid #aaaaaa; + margin: 2pt 2pt 4pt 10pt; + padding: 0pt; +} + +div.Image +{ + border: none; + margin: 2pt; + text-align: center; +} + +pre.InfoLog +{ + background: #ddddee; + margin: 0px; +} + +td.ConfigListTitle +{ + font-weight: bold; + text-align: right; +} + +td.ConfigListValue +{ + text-align: right; +} + +table.Totals +{ + border-collapse: collapse; + text-align: right; +} + +table.Totals td +{ + padding: 2pt 4pt 2pt 4pt; +} + +div.TestCaseResult +{ + border: 1px solid #aaaaaa; + margin: 15pt 2pt 2pt 2pt; + padding: 0pt; +} + +/* Background colors based on status code / status. */ +.Pass { background: #80ff80; } +.Fail { background: #ff4040; } +.QualityWarning { background: #ffff00; } +.CompatibilityWarning { background: #ffff00; } +.Pending { background: #808080; } +.Running { background: #d3d3d3; } +.NotSupported { background: #ff69b4; } +.ResourceError { background: #ff4040; } +.InternalError { background: #ff1493; } +.Canceled { background: #808080; } +.Crash { background: #ffa500; } +.Timeout { background: #ffa500; } +.Disabled { background: #808080; } +.Terminated { background: #ffa500; } +.Missing { background: #808080; } +.OK { background: #80ff80; } diff --git a/conformance/testlog.xsl b/conformance/testlog.xsl new file mode 100644 index 0000000..f8e1400 --- /dev/null +++ b/conformance/testlog.xsl @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + <xsl:value-of select="@FileName"/> + + + + + + + + + + + + + + + + + + +
Total cases
Pass
Fail
Quality warning
Compatibility warning
Not supported
Resource error
Internal error
Timeout
Crash
Disabled
+ + + +
+ + + + + + <xsl:value-of select="@CasePath"/> + + +

: ()

+ + + +
+ + +
+

: ()

+ +
+
+ + +
+

+ +
+
+ + +
+

+ +
+
+ + +
+
+ +
+
+ + +
+

+ +
+
+ + +
+

Shader Program

+ +
+
+ + +
+

Vertex Shader

+ +
+
+ + +
+

Fragment Shader

+ +
+
+ + + :
+
+ + + + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+

+ + + + + + + + + + + + +
IDRGBADSmS
+
+
+ + + + + + + + + + + + + + +
diff --git a/libportability-gfx/Cargo.toml b/libportability-gfx/Cargo.toml index 5fa6483..48b0a84 100644 --- a/libportability-gfx/Cargo.toml +++ b/libportability-gfx/Cargo.toml @@ -25,19 +25,19 @@ optional = true [dependencies.gfx-hal] git = "https://github.com/gfx-rs/gfx" -rev = "eda7f3c570d09f2fd0bf942c3d945a1b62d72af8" +rev = "adbf496f9b56d70cecb4a02aab6ad316e59a391d" [target.'cfg(not(target_os = "macos"))'.dependencies.gfx-backend-vulkan] git = "https://github.com/gfx-rs/gfx" -rev = "eda7f3c570d09f2fd0bf942c3d945a1b62d72af8" +rev = "adbf496f9b56d70cecb4a02aab6ad316e59a391d" optional = true [target.'cfg(windows)'.dependencies.gfx-backend-dx12] git = "https://github.com/gfx-rs/gfx" -rev = "eda7f3c570d09f2fd0bf942c3d945a1b62d72af8" +rev = "adbf496f9b56d70cecb4a02aab6ad316e59a391d" optional = true [target.'cfg(target_os = "macos")'.dependencies.gfx-backend-metal] git = "https://github.com/gfx-rs/gfx" -rev = "eda7f3c570d09f2fd0bf942c3d945a1b62d72af8" +rev = "adbf496f9b56d70cecb4a02aab6ad316e59a391d" optional = true diff --git a/libportability-gfx/src/conv.rs b/libportability-gfx/src/conv.rs index f9d238f..525f2ee 100644 --- a/libportability-gfx/src/conv.rs +++ b/libportability-gfx/src/conv.rs @@ -623,3 +623,24 @@ pub fn map_extent(extent: VkExtent3D) -> image::Extent { depth: extent.depth, } } + +pub fn map_rect(rect: &VkRect2D) -> pso::Rect { + pso::Rect { + x: rect.offset.x as _, + y: rect.offset.y as _, + w: rect.extent.width as _, + h: rect.extent.height as _, + } +} + +pub fn map_viewport(vp: &VkViewport) -> pso::Viewport { + pso::Viewport { + rect: pso::Rect { + x: vp.x as _, + y: vp.y as _, + w: vp.width as _, + h: vp.height as _, + }, + depth: vp.minDepth .. vp.maxDepth, + } +} diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index e8a9800..e522ee7 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -684,7 +684,8 @@ pub extern "C" fn gfxQueueSubmit( } #[inline] pub extern "C" fn gfxQueueWaitIdle(queue: VkQueue) -> VkResult { - unimplemented!() + let _ = queue.wait_idle(); + VkResult::VK_SUCCESS } #[inline] pub extern "C" fn gfxDeviceWaitIdle(device: VkDevice) -> VkResult { @@ -715,7 +716,7 @@ pub extern "C" fn gfxAllocateMemory( pub extern "C" fn gfxFreeMemory( gpu: VkDevice, memory: VkDeviceMemory, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { gpu.device.free_memory(*memory.unwrap()); } @@ -985,7 +986,7 @@ pub extern "C" fn gfxDestroySemaphore( pub extern "C" fn gfxCreateEvent( device: VkDevice, pCreateInfo: *const VkEventCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pEvent: *mut VkEvent, ) -> VkResult { unimplemented!() @@ -994,7 +995,7 @@ pub extern "C" fn gfxCreateEvent( pub extern "C" fn gfxDestroyEvent( device: VkDevice, event: VkEvent, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { unimplemented!() } @@ -1014,7 +1015,7 @@ pub extern "C" fn gfxResetEvent(device: VkDevice, event: VkEvent) -> VkResult { pub extern "C" fn gfxCreateQueryPool( device: VkDevice, pCreateInfo: *const VkQueryPoolCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pQueryPool: *mut VkQueryPool, ) -> VkResult { unimplemented!() @@ -1023,7 +1024,7 @@ pub extern "C" fn gfxCreateQueryPool( pub extern "C" fn gfxDestroyQueryPool( device: VkDevice, queryPool: VkQueryPool, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { unimplemented!() } @@ -1044,7 +1045,7 @@ pub extern "C" fn gfxGetQueryPoolResults( pub extern "C" fn gfxCreateBuffer( gpu: VkDevice, pCreateInfo: *const VkBufferCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pBuffer: *mut VkBuffer, ) -> VkResult { let info = unsafe { &*pCreateInfo }; @@ -1064,37 +1065,57 @@ pub extern "C" fn gfxCreateBuffer( pub extern "C" fn gfxDestroyBuffer( gpu: VkDevice, buffer: VkBuffer, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { if !buffer.is_null() { match *buffer.unwrap() { Buffer::Buffer(buffer) => gpu.device.destroy_buffer(buffer), - Buffer::Unbound(_) => unimplemented!(), + Buffer::Unbound(_) => { + warn!("Trying to destroy a non-bound buffer, ignoring"); + } } } } #[inline] pub extern "C" fn gfxCreateBufferView( - device: VkDevice, + gpu: VkDevice, pCreateInfo: *const VkBufferViewCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pView: *mut VkBufferView, ) -> VkResult { - unimplemented!() + let info = unsafe { &*pCreateInfo }; + + let view = gpu.device + .create_buffer_view( + match *info.buffer { + Buffer::Buffer(ref buffer) => buffer, + Buffer::Unbound(_) => unimplemented!(), + }, + conv::map_format(info.format), + info.offset .. info.offset + info.range, + ) + .expect("Error creating buffer view"); + + unsafe { + *pView = Handle::new(view); + } + VkResult::VK_SUCCESS } #[inline] pub extern "C" fn gfxDestroyBufferView( - device: VkDevice, - bufferView: VkBufferView, - pAllocator: *const VkAllocationCallbacks, + gpu: VkDevice, + view: VkBufferView, + _pAllocator: *const VkAllocationCallbacks, ) { - unimplemented!() + if !view.is_null() { + gpu.device.destroy_buffer_view(*view.unwrap()); + } } #[inline] pub extern "C" fn gfxCreateImage( gpu: VkDevice, pCreateInfo: *const VkImageCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pImage: *mut VkImage, ) -> VkResult { let info = unsafe { &*pCreateInfo }; @@ -1126,12 +1147,14 @@ pub extern "C" fn gfxCreateImage( pub extern "C" fn gfxDestroyImage( gpu: VkDevice, image: VkImage, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { if !image.is_null() { match *image.unwrap() { Image::Image(image) => gpu.device.destroy_image(image), - Image::Unbound(_) => unimplemented!(), + Image::Unbound(_) => { + warn!("Trying to destroy a non-bound image, ignoring"); + } } } } @@ -1148,7 +1171,7 @@ pub extern "C" fn gfxGetImageSubresourceLayout( pub extern "C" fn gfxCreateImageView( gpu: VkDevice, pCreateInfo: *const VkImageViewCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pView: *mut VkImageView, ) -> VkResult { let info = unsafe { &*pCreateInfo }; @@ -1181,7 +1204,7 @@ pub extern "C" fn gfxCreateImageView( pub extern "C" fn gfxDestroyImageView( gpu: VkDevice, imageView: VkImageView, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { gpu.device.destroy_image_view(*imageView.unwrap()) } @@ -1219,7 +1242,7 @@ pub extern "C" fn gfxDestroyShaderModule( pub extern "C" fn gfxCreatePipelineCache( device: VkDevice, pCreateInfo: *const VkPipelineCacheCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pPipelineCache: *mut VkPipelineCache, ) -> VkResult { // unimplemented!() @@ -1231,7 +1254,7 @@ pub extern "C" fn gfxCreatePipelineCache( pub extern "C" fn gfxDestroyPipelineCache( device: VkDevice, pipelineCache: VkPipelineCache, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { unimplemented!() } @@ -1315,8 +1338,6 @@ pub extern "C" fn gfxCreateGraphicsPipelines( let mut cur_shader_stage = 0; let descs = infos.into_iter().map(|info| { - // TODO: handle dynamic states and viewports - let shaders = { let mut set: pso::GraphicsShaderSet<_> = unsafe { mem::zeroed() }; @@ -1530,6 +1551,35 @@ pub extern "C" fn gfxCreateGraphicsPipelines( }) }; + let vp_state = unsafe { &*info.pViewportState }; + let empty_dyn_states = []; + let dyn_states = match unsafe { info.pDynamicState.as_ref() } { + Some(state) => unsafe { + slice::from_raw_parts(state.pDynamicStates, state.dynamicStateCount as _) + }, + None => &empty_dyn_states, + }; + let baked_states = pso::BakedStates { + viewport: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_VIEWPORT) { + None + } else { + unsafe { vp_state.pViewports.as_ref() } + .map(conv::map_viewport) + }, + scissor: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_SCISSOR) { + None + } else { + unsafe { vp_state.pScissors.as_ref() } + .map(conv::map_rect) + }, + blend_color: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_BLEND_CONSTANTS) { + None + } else { + unsafe { info.pColorBlendState.as_ref() } + .map(|cbs| cbs.blendConstants) + }, + }; + let layout = &*info.layout; let subpass = pass::Subpass { index: info.subpass as _, @@ -1572,6 +1622,7 @@ pub extern "C" fn gfxCreateGraphicsPipelines( input_assembler, blender, depth_stencil, + baked_states, layout, subpass, flags, @@ -1601,7 +1652,7 @@ pub extern "C" fn gfxCreateComputePipelines( pipelineCache: VkPipelineCache, createInfoCount: u32, pCreateInfos: *const VkComputePipelineCreateInfo, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pPipelines: *mut VkPipeline, ) -> VkResult { unimplemented!() @@ -1610,7 +1661,7 @@ pub extern "C" fn gfxCreateComputePipelines( pub extern "C" fn gfxDestroyPipeline( gpu: VkDevice, pipeline: VkPipeline, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { if !pipeline.is_null() { match *pipeline.unwrap() { @@ -2233,7 +2284,7 @@ pub extern "C" fn gfxAllocateCommandBuffers( #[inline] pub extern "C" fn gfxFreeCommandBuffers( _gpu: VkDevice, - mut commandPool: VkCommandPool, + commandPool: VkCommandPool, commandBufferCount: u32, pCommandBuffers: *const VkCommandBuffer, ) { @@ -2291,17 +2342,7 @@ pub extern "C" fn gfxCmdSetViewport( let viewports = unsafe { slice::from_raw_parts(pViewports, viewportCount as _) .into_iter() - .map(|viewport| { - com::Viewport { - rect: com::Rect { - x: viewport.x as _, - y: viewport.y as _, - w: viewport.width as _, - h: viewport.height as _, - }, - depth: viewport.minDepth .. viewport.maxDepth, - } - }) + .map(conv::map_viewport) }; commandBuffer.set_viewports(viewports); @@ -2318,14 +2359,7 @@ pub extern "C" fn gfxCmdSetScissor( let scissors = unsafe { slice::from_raw_parts(pScissors, scissorCount as _) .into_iter() - .map(|scissor| { - com::Rect { - x: scissor.offset.x as _, - y: scissor.offset.y as _, - w: scissor.extent.width as _, - h: scissor.extent.height as _, - } - }) + .map(conv::map_rect) }; commandBuffer.set_scissors(scissors); @@ -2855,7 +2889,7 @@ pub extern "C" fn gfxCmdBeginRenderPass( ) { let info = unsafe { &*pRenderPassBegin }; - let render_area = com::Rect { + let render_area = pso::Rect { x: info.renderArea.offset.x as _, y: info.renderArea.offset.y as _, w: info.renderArea.extent.width as _, @@ -3049,7 +3083,7 @@ pub extern "C" fn gfxCreateSwapchainKHR( pub extern "C" fn gfxDestroySwapchainKHR( device: VkDevice, mut swapchain: VkSwapchainKHR, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { for image in &mut swapchain.images { let _ = image.unwrap(); @@ -3106,7 +3140,7 @@ pub extern "C" fn gfxCmdReserveSpaceForCommandsNVX( pub extern "C" fn gfxCreateIndirectCommandsLayoutNVX( device: VkDevice, pCreateInfo: *const VkIndirectCommandsLayoutCreateInfoNVX, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pIndirectCommandsLayout: *mut VkIndirectCommandsLayoutNVX, ) -> VkResult { unimplemented!() @@ -3115,7 +3149,7 @@ pub extern "C" fn gfxCreateIndirectCommandsLayoutNVX( pub extern "C" fn gfxDestroyIndirectCommandsLayoutNVX( device: VkDevice, indirectCommandsLayout: VkIndirectCommandsLayoutNVX, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { unimplemented!() } @@ -3123,7 +3157,7 @@ pub extern "C" fn gfxDestroyIndirectCommandsLayoutNVX( pub extern "C" fn gfxCreateObjectTableNVX( device: VkDevice, pCreateInfo: *const VkObjectTableCreateInfoNVX, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pObjectTable: *mut VkObjectTableNVX, ) -> VkResult { unimplemented!() @@ -3132,7 +3166,7 @@ pub extern "C" fn gfxCreateObjectTableNVX( pub extern "C" fn gfxDestroyObjectTableNVX( device: VkDevice, objectTable: VkObjectTableNVX, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, ) { unimplemented!() } @@ -3200,7 +3234,7 @@ pub extern "C" fn gfxDisplayPowerControlEXT( pub extern "C" fn gfxRegisterDeviceEventEXT( device: VkDevice, pDeviceEventInfo: *const VkDeviceEventInfoEXT, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pFence: *mut VkFence, ) -> VkResult { unimplemented!() @@ -3210,7 +3244,7 @@ pub extern "C" fn gfxRegisterDisplayEventEXT( device: VkDevice, display: VkDisplayKHR, pDisplayEventInfo: *const VkDisplayEventInfoEXT, - pAllocator: *const VkAllocationCallbacks, + _pAllocator: *const VkAllocationCallbacks, pFence: *mut VkFence, ) -> VkResult { unimplemented!() @@ -3240,12 +3274,12 @@ pub extern "C" fn gfxCreateWin32SurfaceKHR( pAllocator: *const VkAllocationCallbacks, pSurface: *mut VkSurfaceKHR, ) -> VkResult { + assert!(pAllocator.is_null()); let info = unsafe { &*pCreateInfo }; #[cfg(all(feature = "gfx-backend-vulkan", target_os = "windows"))] { unsafe { assert_eq!(info.flags, 0); - assert!(pAllocator.is_null()); *pSurface = Handle::new( instance.backend.create_surface_from_hwnd(info.hinstance, info.hwnd), ); @@ -3256,7 +3290,6 @@ pub extern "C" fn gfxCreateWin32SurfaceKHR( { unsafe { assert_eq!(info.flags, 0); - assert!(pAllocator.is_null()); *pSurface = Handle::new(instance.backend.create_surface_from_hwnd(info.hwnd)); VkResult::VK_SUCCESS } @@ -3270,12 +3303,12 @@ pub extern "C" fn gfxCreateXcbSurfaceKHR( pAllocator: *const VkAllocationCallbacks, pSurface: *mut VkSurfaceKHR, ) -> VkResult { + assert!(pAllocator.is_null()); let info = unsafe { &*pCreateInfo }; #[cfg(all(feature = "gfx-backend-vulkan", target_os = "linux"))] { unsafe { assert_eq!(info.flags, 0); - assert!(pAllocator.is_null()); *pSurface = Handle::new( instance.backend.create_surface_from_xcb(info.connection as _, info.window), );