Skip to content

Commit

Permalink
[warden] better state handling, logging, dx12 fix
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Oct 18, 2017
1 parent d7b688f commit 02c50d2
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 31 deletions.
4 changes: 2 additions & 2 deletions src/backend/dx12/src/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ pub fn map_buffer_resource_state(access: buffer::Access) -> D3D12_RESOURCE_STATE
let mut state = D3D12_RESOURCE_STATE_COMMON;

if access.contains(buffer::TRANSFER_READ) {
state = state | D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_RESOLVE_DEST;
state = state | D3D12_RESOURCE_STATE_COPY_SOURCE;
}
if access.contains(buffer::INDEX_BUFFER_READ) {
state = state | D3D12_RESOURCE_STATE_INDEX_BUFFER;
Expand Down Expand Up @@ -472,7 +472,7 @@ pub fn map_image_resource_state(access: image::Access, layout: image::ImageLayou
let mut state = D3D12_RESOURCE_STATE_COMMON;

if access.contains(image::TRANSFER_READ) {
state = state | D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_RESOLVE_DEST;
state = state | D3D12_RESOURCE_STATE_COPY_SOURCE;
}
if access.contains(image::INPUT_ATTACHMENT_READ) {
state = state | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
Expand Down
3 changes: 2 additions & 1 deletion src/backend/gl/src/window/glutin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ pub fn config_context(

pub struct Headless(pub glutin::HeadlessContext);

impl core::Instance<B> for Headless {
impl core::Instance for Headless {
type Backend = B;
fn enumerate_adapters(&self) -> Vec<Adapter> {
unsafe { self.0.make_current().unwrap() };
let adapter = Adapter::new(|s| self.0.get_proc_address(s) as *const _);
Expand Down
4 changes: 2 additions & 2 deletions src/render/src/allocators/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<B: Backend> Allocator<B> for StackAllocator<B> {
device.mut_raw(), &buffer, usage);
let memory_type = device.find_usage_memory(inner.usage, requirements.type_mask)
.expect("could not find suitable memory");
let mut stack = inner.stacks.entry(memory_type.id)
let stack = inner.stacks.entry(memory_type.id)
.or_insert_with(|| ChunkStack::new(memory_type));
let (memory, offset, release) = stack.allocate(
device,
Expand All @@ -91,7 +91,7 @@ impl<B: Backend> Allocator<B> for StackAllocator<B> {
let requirements = device.mut_raw().get_image_requirements(&image);
let memory_type = device.find_usage_memory(inner.usage, requirements.type_mask)
.expect("could not find suitable memory");
let mut stack = inner.stacks.entry(memory_type.id)
let stack = inner.stacks.entry(memory_type.id)
.or_insert_with(|| ChunkStack::new(memory_type));
let (memory, offset, release) = stack.allocate(
device,
Expand Down
2 changes: 1 addition & 1 deletion src/render/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ macro_rules! gfx_graphics_pipeline {
preserves: &[],
};

device.create_renderpass_raw(&attachments[..], &[subpass], &[])
device.create_render_pass_raw(&attachments[..], &[subpass], &[])
};

let mut pipeline_desc = cpso::GraphicsPipelineDesc::new(
Expand Down
4 changes: 3 additions & 1 deletion src/warden/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ path = "src/lib.rs"

[features]
default = []
logger = ["env_logger"]
vulkan = ["gfx-backend-vulkan"]
dx12 = ["gfx-backend-dx12"]
metal = ["gfx-backend-metal"]
Expand All @@ -26,9 +27,10 @@ metal = ["gfx-backend-metal"]

[dependencies]
gfx-hal = { path = "../hal", version = "0.1", features = ["serialize"] }
#log = "0.3"
log = "0.3"
ron = "0.1"
serde = { version = "1.0", features = ["serde_derive"] }
env_logger = { version = "0.4", optional = true }

[dependencies.gfx-backend-vulkan]
path = "../../src/backend/vulkan"
Expand Down
10 changes: 5 additions & 5 deletions src/warden/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Warden

Warden is the data-driver reference test framework for gfx-rs Hardware Abstraction Layer (gfx-hal), heavily inspired by the Wrench component of [WebRender](https://github.com/servo/webrender/). Warden's main purpose is to run a suite of GPU workloads on all native backends supported by the host platform, then match the results against provided expectations. Both the workloads and expectations are backend-agnostic. The backend discovery and initialization is done by the `reftest` binary. All that needs to be done by a developer is typing `make reftests` from the project root and ensuring that every test passes.
Warden is the data-driven reference test framework for gfx-rs Hardware Abstraction Layer (`gfx-hal`), heavily inspired by the Wrench component of [WebRender](https://github.com/servo/webrender/). Warden's main purpose is to run a suite of GPU workloads on all native backends supported by the host platform, then match the results against provided expectations. Both the workloads and expectations are backend-agnostic. The backend discovery and initialization is done by the `reftest` binary. All that needs to be done by a developer is typing `make reftests` from the project root and ensuring that every test passes.

Warden has two types of definitions: scene and suite. Both are written in [Ron](https://github.com/ron-rs/ron), but technically the code should work with any `serde`-enabled format given minimal tweaking.
Warden has two types of definitions: scene and suite. Both are written in [Ron](https://github.com/ron-rs/ron) format, but technically the code should work with any `serde`-enabled format given minimal tweaking.

## Scene definition

Expand All @@ -12,12 +12,12 @@ A scene consists of a number of resources and jobs that can be run on them. Reso

Internally, a scene has a command buffer to fill up all the initial data for resources. This command buffer needs to change the resource access and image layouts, so we establish a convention here by which every resource has an associated "stable" state that the user (and the reftest framework) promises to deliver at the end of each job.

For images with no source data, the stable layout is `ColorAttachmentOptimal` or `DepthStencilAttachmentOptimal` depending on the format.
For images with no source data, the stable layout is `ColorAttachmentOptimal` or `DepthStencilAttachmentOptimal` depending on the format. For sourced images, it's `ShaderReadOnlyOptimal`.

## Test suite

A test suite is just a set of scenes, each having a set of tests. A test is defined as a sequence of jobs being run on the scene and an expectation result. The central suite file can be found in [reftests](../../reftests/suite.ron).
A test suite is just a set of scenes, each with multiple tests. A test is defined as a sequence of jobs being run on the scene and an expectation result. The central suite file can be found in [reftests](../../reftests/suite.ron), and the serialization structures are in [reftest.rs](src/bin/reftest.rs).

## Warning

This gfx-rs component is heavy WIP, there is a lot of logic missing, especially with regards to error reporting.
This gfx-rs component is heavy WIP, provided under no warranty! There is a lot of logic missing, especially with regards to error reporting.
7 changes: 6 additions & 1 deletion src/warden/src/bin/reftest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ extern crate ron;
#[macro_use]
extern crate serde;

#[cfg(feature = "logger")]
extern crate env_logger;
#[cfg(feature = "vulkan")]
extern crate gfx_backend_vulkan;
#[cfg(feature = "dx12")]
Expand Down Expand Up @@ -92,6 +94,9 @@ impl Harness {
}

fn main() {
#[cfg(feature = "logger")]
env_logger::init().unwrap();

let harness = Harness::new("suite");
#[cfg(feature = "vulkan")]
{
Expand All @@ -101,7 +106,7 @@ fn main() {
}
#[cfg(feature = "dx12")]
{
println!("Warding Dx12:");
println!("Warding DX12:");
let instance = gfx_backend_dx12::Instance::create("warden", 1);
harness.run(instance);
}
Expand Down
62 changes: 44 additions & 18 deletions src/warden/src/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ pub struct Image<B: hal::Backend> {
pub handle: B::Image,
#[allow(dead_code)]
memory: B::Memory,
kind: hal::image::Kind,
kind: i::Kind,
format: hal::format::Format,
stable_state: i::State,
}

pub struct RenderPass<B: hal::Backend> {
Expand Down Expand Up @@ -90,6 +91,7 @@ fn align(x: usize, y: usize) -> usize {

impl<B: hal::Backend> Scene<B> {
pub fn new(adapter: &B::Adapter, raw: &raw::Scene, data_path: &str) -> Self {
info!("creating Scene from {}", data_path);
// initialize graphics
let hal::Gpu { mut device, mut graphics_queues, memory_types, .. } = {
let (ref family, queue_type) = adapter.get_queue_families()[0];
Expand All @@ -110,6 +112,9 @@ impl<B: hal::Backend> Scene<B> {
})
.unwrap()
.clone();
info!("upload memory: {:?}", upload_type);
info!("download memory: {:?}", &download_type);

let limits = device.get_limits().clone();
let queue = graphics_queues.remove(0);
let mut command_pool = queue.create_graphics_pool(
Expand Down Expand Up @@ -153,20 +158,39 @@ impl<B: hal::Backend> Scene<B> {
.unwrap();
let image = device.bind_image_memory(&memory, 0, unbound)
.unwrap();
let bits = format.0.describe_bits();

// process initial data for the image
if !data.is_empty() {
let stable_state = if data.is_empty() {
let (aspects, access, layout) = if bits.color != 0 {
(i::ASPECT_COLOR, i::COLOR_ATTACHMENT_WRITE, i::ImageLayout::ColorAttachmentOptimal)
} else {
(i::ASPECT_DEPTH | i::ASPECT_STENCIL, i::DEPTH_STENCIL_ATTACHMENT_WRITE, i::ImageLayout::DepthStencilAttachmentOptimal)
};
if false { //TODO
let image_barrier = hal::memory::Barrier::Image {
states: (i::Access::empty(), i::ImageLayout::Undefined) .. (access, layout),
target: &image,
range: i::SubresourceRange {
aspects,
.. COLOR_RANGE.clone()
},
};
init_cmd.pipeline_barrier(hal::pso::TOP_OF_PIPE .. hal::pso::BOTTOM_OF_PIPE, &[image_barrier]);
}
(access, layout)
} else {
// calculate required sizes
let (w, h, d, aa) = kind.get_dimensions();
assert_eq!(aa, i::AaMode::Single);
let bpp = format.0.describe_bits().total as usize;
let width_bytes = bpp * w as usize / 8;
let width_bytes = bits.total as usize * w as usize / 8;
let row_pitch = align(width_bytes, limits.min_buffer_copy_pitch_alignment);
let upload_size = row_pitch as u64 * h as u64 * d as u64;
// create upload buffer
let unbound_buffer = device.create_buffer(upload_size, bpp as _, hal::buffer::TRANSFER_SRC)
let unbound_buffer = device.create_buffer(upload_size, bits.total as _, hal::buffer::TRANSFER_SRC)
.unwrap();
let upload_req = device.get_buffer_requirements(&unbound_buffer);
assert_ne!(upload_req.type_mask & (1<<upload_type.id), 0);
let upload_memory = device.allocate_memory(upload_type, upload_req.size)
.unwrap();
let upload_buffer = device.bind_buffer_memory(&upload_memory, 0, unbound_buffer)
Expand All @@ -185,11 +209,12 @@ impl<B: hal::Backend> Scene<B> {
device.release_mapping_writer(mapping);
}
// add init commands
let final_state = (i::SHADER_READ, i::ImageLayout::ShaderReadOnlyOptimal);
let image_barrier = hal::memory::Barrier::Image {
states: (i::Access::empty(), i::ImageLayout::Undefined) ..
(i::TRANSFER_WRITE, i::ImageLayout::TransferDstOptimal),
target: &image,
range: COLOR_RANGE.clone(),
range: COLOR_RANGE.clone(), //TODO
};
init_cmd.pipeline_barrier(hal::pso::TOP_OF_PIPE .. hal::pso::TRANSFER, &[image_barrier]);
init_cmd.copy_buffer_to_image(
Expand All @@ -213,21 +238,22 @@ impl<B: hal::Backend> Scene<B> {
},
}]);
let image_barrier = hal::memory::Barrier::Image {
states: (i::TRANSFER_WRITE, i::ImageLayout::TransferDstOptimal) ..
(i::SHADER_READ, i::ImageLayout::ShaderReadOnlyOptimal),
states: (i::TRANSFER_WRITE, i::ImageLayout::TransferDstOptimal) .. final_state,
target: &image,
range: COLOR_RANGE.clone(),
range: COLOR_RANGE.clone(), //TODO
};
init_cmd.pipeline_barrier(hal::pso::TRANSFER .. hal::pso::BOTTOM_OF_PIPE, &[image_barrier]);
// done
upload_buffers.insert(name.clone(), (upload_buffer, upload_memory));
}
final_state
};

resources.images.insert(name.clone(), Image {
handle: image,
memory,
kind,
format,
stable_state,
});
}
raw::Resource::RenderPass { ref attachments, ref subpasses, ref dependencies } => {
Expand Down Expand Up @@ -385,6 +411,7 @@ impl<B: hal::Backend> Scene<B> {
}
}
raw::Job::Graphics { ref descriptors, ref framebuffer, ref pass, ref clear_values } => {
let _ = descriptors; //TODO
let (ref fb, extent) = resources.framebuffers[framebuffer];
let rp = &resources.render_passes[&pass.0];
let rect = hal::target::Rect {
Expand Down Expand Up @@ -419,10 +446,10 @@ impl<B: hal::Backend> Scene<B> {
let set = hal::pso::VertexBufferSet(buffers_raw);
encoder.bind_vertex_buffers(set);
}
Dc::BindPipeline(ref name) => {
Dc::BindPipeline(_) => {
unimplemented!()
}
Dc::BindDescriptorSets { ref layout, first, ref sets } => {
Dc::BindDescriptorSets { .. } => { //ref layout, first, ref sets
unimplemented!()
}
Dc::Draw { ref vertices, ref instances } => {
Expand Down Expand Up @@ -482,6 +509,7 @@ impl<B: hal::Backend> Scene<B> {
let unbound_buffer = self.device.create_buffer(down_size, bpp as _, hal::buffer::TRANSFER_DST)
.unwrap();
let down_req = self.device.get_buffer_requirements(&unbound_buffer);
assert_ne!(down_req.type_mask & (1<<self.download_type.id), 0);
let down_memory = self.device.allocate_memory(&self.download_type, down_req.size)
.unwrap();
let down_buffer = self.device.bind_buffer_memory(&down_memory, 0, unbound_buffer)
Expand All @@ -494,10 +522,9 @@ impl<B: hal::Backend> Scene<B> {
let copy_submit = {
let mut cmd_buffer = command_pool.acquire_command_buffer();
let image_barrier = hal::memory::Barrier::Image {
states: (i::SHADER_READ, i::ImageLayout::ShaderReadOnlyOptimal) ..
(i::TRANSFER_READ, i::ImageLayout::TransferSrcOptimal),
states: image.stable_state .. (i::TRANSFER_READ, i::ImageLayout::TransferSrcOptimal),
target: &image.handle,
range: COLOR_RANGE.clone(),
range: COLOR_RANGE.clone(), //TODO
};
cmd_buffer.pipeline_barrier(hal::pso::TOP_OF_PIPE .. hal::pso::TRANSFER, &[image_barrier]);
cmd_buffer.copy_image_to_buffer(
Expand All @@ -521,10 +548,9 @@ impl<B: hal::Backend> Scene<B> {
},
}]);
let image_barrier = hal::memory::Barrier::Image {
states: (i::TRANSFER_READ, i::ImageLayout::TransferSrcOptimal) ..
(i::SHADER_READ, i::ImageLayout::ShaderReadOnlyOptimal),
states: (i::TRANSFER_READ, i::ImageLayout::TransferSrcOptimal) .. image.stable_state,
target: &image.handle,
range: COLOR_RANGE.clone(),
range: COLOR_RANGE.clone(), //TODO
};
cmd_buffer.pipeline_barrier(hal::pso::TRANSFER .. hal::pso::BOTTOM_OF_PIPE, &[image_barrier]);
cmd_buffer.finish()
Expand Down
2 changes: 2 additions & 0 deletions src/warden/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

extern crate gfx_hal as hal;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde;

pub mod gpu;
Expand Down

0 comments on commit 02c50d2

Please sign in to comment.