vulkan: pre-processes GfxApiOpt
This commit is contained in:
parent
135f37dbcd
commit
db4ff00330
1 changed files with 219 additions and 135 deletions
|
|
@ -31,10 +31,7 @@ use {
|
||||||
io_uring::IoUring,
|
io_uring::IoUring,
|
||||||
rect::{Rect, Region},
|
rect::{Rect, Region},
|
||||||
theme::{Color, TransferFunction},
|
theme::{Color, TransferFunction},
|
||||||
utils::{
|
utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, stack::Stack},
|
||||||
copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, once::Once,
|
|
||||||
stack::Stack,
|
|
||||||
},
|
|
||||||
video::dmabuf::{DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, dma_buf_export_sync_file},
|
video::dmabuf::{DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, dma_buf_export_sync_file},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
|
@ -55,13 +52,15 @@ use {
|
||||||
},
|
},
|
||||||
isnt::std_1::{collections::IsntHashMapExt, primitive::IsntSliceExt},
|
isnt::std_1::{collections::IsntHashMapExt, primitive::IsntSliceExt},
|
||||||
jay_algorithms::rect::Tag,
|
jay_algorithms::rect::Tag,
|
||||||
linearize::{Linearize, StaticMap, static_map},
|
linearize::{Linearize, LinearizeExt, StaticMap, static_map},
|
||||||
std::{
|
std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
collections::hash_map::Entry,
|
collections::hash_map::Entry,
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
mem, ptr,
|
mem,
|
||||||
|
ops::Range,
|
||||||
|
ptr,
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
slice,
|
slice,
|
||||||
},
|
},
|
||||||
|
|
@ -128,13 +127,13 @@ pub(super) struct UsedTexture {
|
||||||
release_sync: ReleaseSync,
|
release_sync: ReleaseSync,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Linearize)]
|
#[derive(Copy, Clone, Linearize)]
|
||||||
pub(super) enum TexCopyType {
|
pub(super) enum TexCopyType {
|
||||||
Identity,
|
Identity,
|
||||||
Multiply,
|
Multiply,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Linearize)]
|
#[derive(Copy, Clone, Linearize)]
|
||||||
pub(super) enum TexSourceType {
|
pub(super) enum TexSourceType {
|
||||||
Opaque,
|
Opaque,
|
||||||
HasAlpha,
|
HasAlpha,
|
||||||
|
|
@ -158,6 +157,33 @@ pub(super) struct Memory {
|
||||||
resource_descriptor_buffer_writer: VulkanDescriptorBufferWriter,
|
resource_descriptor_buffer_writer: VulkanDescriptorBufferWriter,
|
||||||
regions_1: Vec<Rect>,
|
regions_1: Vec<Rect>,
|
||||||
regions_2: Vec<Rect<u32>>,
|
regions_2: Vec<Rect<u32>>,
|
||||||
|
ops: StaticMap<RenderPass, Vec<VulkanOp>>,
|
||||||
|
fill_targets: Vec<Point>,
|
||||||
|
tex_targets: Vec<[Point; 2]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Point = [[f32; 2]; 4];
|
||||||
|
|
||||||
|
enum VulkanOp {
|
||||||
|
Fill(VulkanFillOp),
|
||||||
|
Tex(VulkanTexOp),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VulkanTexOp {
|
||||||
|
tex: Rc<VulkanImage>,
|
||||||
|
range: Range<usize>,
|
||||||
|
buffer_resv: Option<Rc<dyn BufferResv>>,
|
||||||
|
acquire_sync: AcquireSync,
|
||||||
|
release_sync: ReleaseSync,
|
||||||
|
alpha: f32,
|
||||||
|
source_type: TexSourceType,
|
||||||
|
copy_type: TexCopyType,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VulkanFillOp {
|
||||||
|
range: Range<usize>,
|
||||||
|
color: [f32; 4],
|
||||||
|
source_type: TexSourceType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Linearize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Linearize, Eq, PartialEq)]
|
||||||
|
|
@ -375,7 +401,6 @@ impl VulkanRenderer {
|
||||||
fn create_descriptor_buffers(
|
fn create_descriptor_buffers(
|
||||||
&self,
|
&self,
|
||||||
buf: CommandBuffer,
|
buf: CommandBuffer,
|
||||||
opts: &[GfxApiOpt],
|
|
||||||
bb: Option<&VulkanImage>,
|
bb: Option<&VulkanImage>,
|
||||||
) -> Result<(), VulkanError> {
|
) -> Result<(), VulkanError> {
|
||||||
let Some(db) = &self.device.descriptor_buffer else {
|
let Some(db) = &self.device.descriptor_buffer else {
|
||||||
|
|
@ -396,21 +421,23 @@ impl VulkanRenderer {
|
||||||
let mut writer = resource_writer.add_set(layout);
|
let mut writer = resource_writer.add_set(layout);
|
||||||
writer.write(layout.offsets[0], &bb.sampled_image_descriptor);
|
writer.write(layout.offsets[0], &bb.sampled_image_descriptor);
|
||||||
}
|
}
|
||||||
for cmd in opts {
|
for pass in RenderPass::variants() {
|
||||||
let GfxApiOpt::CopyTexture(c) = cmd else {
|
for cmd in &memory.ops[pass] {
|
||||||
continue;
|
let VulkanOp::Tex(c) = cmd else {
|
||||||
};
|
continue;
|
||||||
let tex = c.tex.clone().into_vk(&self.device.device);
|
};
|
||||||
if tex.descriptor_buffer_version.replace(version) == version {
|
let tex = &c.tex;
|
||||||
continue;
|
if tex.descriptor_buffer_version.replace(version) == version {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let offset = sampler_writer.next_offset();
|
||||||
|
tex.descriptor_buffer_offset.set(offset);
|
||||||
|
let mut writer = sampler_writer.add_set(&self.tex_descriptor_set_layout);
|
||||||
|
writer.write(
|
||||||
|
self.tex_descriptor_set_layout.offsets[0],
|
||||||
|
&tex.shader_read_only_optimal_descriptor,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let offset = sampler_writer.next_offset();
|
|
||||||
tex.descriptor_buffer_offset.set(offset);
|
|
||||||
let mut writer = sampler_writer.add_set(&self.tex_descriptor_set_layout);
|
|
||||||
writer.write(
|
|
||||||
self.tex_descriptor_set_layout.offsets[0],
|
|
||||||
&tex.shader_read_only_optimal_descriptor,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let mut infos = ArrayVec::<_, 2>::new();
|
let mut infos = ArrayVec::<_, 2>::new();
|
||||||
for (writer, cache) in [
|
for (writer, cache) in [
|
||||||
|
|
@ -433,35 +460,131 @@ impl VulkanRenderer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_memory(&self, opts: &[GfxApiOpt]) {
|
fn convert_ops(&self, opts: &[GfxApiOpt]) {
|
||||||
|
zone!("convert_ops");
|
||||||
|
let memory = &mut *self.memory.borrow_mut();
|
||||||
|
for ops in memory.ops.values_mut() {
|
||||||
|
ops.clear();
|
||||||
|
}
|
||||||
|
memory.tex_targets.clear();
|
||||||
|
memory.fill_targets.clear();
|
||||||
|
for op in opts {
|
||||||
|
match op {
|
||||||
|
GfxApiOpt::Sync => {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
GfxApiOpt::FillRect(fr) => {
|
||||||
|
let target = fr.rect.to_points();
|
||||||
|
for pass in RenderPass::variants() {
|
||||||
|
let tf = match pass {
|
||||||
|
RenderPass::BlendBuffer => TransferFunction::Linear,
|
||||||
|
RenderPass::FrameBuffer => TransferFunction::Srgb,
|
||||||
|
};
|
||||||
|
let ops = &mut memory.ops[pass];
|
||||||
|
let lo = memory.fill_targets.len();
|
||||||
|
for region in &memory.paint_regions[pass] {
|
||||||
|
let mut target = target;
|
||||||
|
if !region.constrain(&mut target, None) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memory.fill_targets.push(target);
|
||||||
|
}
|
||||||
|
let hi = memory.fill_targets.len();
|
||||||
|
if lo == hi {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let color = fr.color.to_array2(tf, fr.alpha);
|
||||||
|
let source_type = match color[3] < 1.0 {
|
||||||
|
false => TexSourceType::Opaque,
|
||||||
|
true => TexSourceType::HasAlpha,
|
||||||
|
};
|
||||||
|
ops.push(VulkanOp::Fill(VulkanFillOp {
|
||||||
|
range: lo..hi,
|
||||||
|
color,
|
||||||
|
source_type,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GfxApiOpt::CopyTexture(ct) => {
|
||||||
|
let tex = ct.tex.clone().into_vk(&self.device.device);
|
||||||
|
if tex.contents_are_undefined.get() {
|
||||||
|
log::warn!("Ignoring undefined texture");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if tex.queue_state.get().acquire(QueueFamily::Gfx) == QueueTransfer::Impossible
|
||||||
|
{
|
||||||
|
log::warn!("Ignoring texture owned by different queue");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let target = ct.target.to_points();
|
||||||
|
let source = ct.source.to_points();
|
||||||
|
for pass in RenderPass::variants() {
|
||||||
|
let ops = &mut memory.ops[pass];
|
||||||
|
let lo = memory.tex_targets.len();
|
||||||
|
for region in &memory.paint_regions[pass] {
|
||||||
|
let mut target = target;
|
||||||
|
let mut source = source;
|
||||||
|
if !region.constrain(&mut target, Some(&mut source)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memory.tex_targets.push([target, source]);
|
||||||
|
}
|
||||||
|
let hi = memory.tex_targets.len();
|
||||||
|
if lo == hi {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let copy_type = match ct.alpha.is_some() {
|
||||||
|
true => TexCopyType::Multiply,
|
||||||
|
false => TexCopyType::Identity,
|
||||||
|
};
|
||||||
|
let source_type = match tex.format.has_alpha && !ct.opaque {
|
||||||
|
true => TexSourceType::HasAlpha,
|
||||||
|
false => TexSourceType::Opaque,
|
||||||
|
};
|
||||||
|
ops.push(VulkanOp::Tex(VulkanTexOp {
|
||||||
|
tex: tex.clone(),
|
||||||
|
range: lo..hi,
|
||||||
|
buffer_resv: ct.buffer_resv.clone(),
|
||||||
|
acquire_sync: ct.acquire_sync.clone(),
|
||||||
|
release_sync: ct.release_sync,
|
||||||
|
alpha: ct.alpha.unwrap_or_default(),
|
||||||
|
source_type,
|
||||||
|
copy_type,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_memory(&self) {
|
||||||
zone!("collect_memory");
|
zone!("collect_memory");
|
||||||
let mut memory = self.memory.borrow_mut();
|
let memory = &mut *self.memory.borrow_mut();
|
||||||
memory.dmabuf_sample.clear();
|
memory.dmabuf_sample.clear();
|
||||||
memory.queue_transfer.clear();
|
memory.queue_transfer.clear();
|
||||||
let execution = self.allocate_point();
|
let execution = self.allocate_point();
|
||||||
for cmd in opts {
|
for pass in RenderPass::variants() {
|
||||||
if let GfxApiOpt::CopyTexture(c) = cmd {
|
for cmd in &memory.ops[pass] {
|
||||||
let tex = c.tex.clone().into_vk(&self.device.device);
|
if let VulkanOp::Tex(c) = cmd {
|
||||||
if tex.contents_are_undefined.get() {
|
let tex = &c.tex;
|
||||||
continue;
|
if tex.execution_version.replace(execution) == execution {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match tex.queue_state.get().acquire(QueueFamily::Gfx) {
|
||||||
|
QueueTransfer::Unnecessary => {}
|
||||||
|
QueueTransfer::Possible => memory.queue_transfer.push(tex.clone()),
|
||||||
|
QueueTransfer::Impossible => continue,
|
||||||
|
}
|
||||||
|
if let VulkanImageMemory::DmaBuf(_) = &tex.ty {
|
||||||
|
memory.dmabuf_sample.push(tex.clone())
|
||||||
|
}
|
||||||
|
memory.textures.push(UsedTexture {
|
||||||
|
tex: tex.clone(),
|
||||||
|
resv: c.buffer_resv.clone(),
|
||||||
|
acquire_sync: c.acquire_sync.clone(),
|
||||||
|
release_sync: c.release_sync,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if tex.execution_version.replace(execution) == execution {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
match tex.queue_state.get().acquire(QueueFamily::Gfx) {
|
|
||||||
QueueTransfer::Unnecessary => {}
|
|
||||||
QueueTransfer::Possible => memory.queue_transfer.push(tex.clone()),
|
|
||||||
QueueTransfer::Impossible => continue,
|
|
||||||
}
|
|
||||||
if let VulkanImageMemory::DmaBuf(_) = &tex.ty {
|
|
||||||
memory.dmabuf_sample.push(tex.clone())
|
|
||||||
}
|
|
||||||
memory.textures.push(UsedTexture {
|
|
||||||
tex,
|
|
||||||
resv: c.buffer_resv.clone(),
|
|
||||||
acquire_sync: c.acquire_sync.clone(),
|
|
||||||
release_sync: c.release_sync,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -680,12 +803,10 @@ impl VulkanRenderer {
|
||||||
&self,
|
&self,
|
||||||
buf: CommandBuffer,
|
buf: CommandBuffer,
|
||||||
target: &VulkanImage,
|
target: &VulkanImage,
|
||||||
opts: &[GfxApiOpt],
|
|
||||||
pass: RenderPass,
|
pass: RenderPass,
|
||||||
) -> Result<(), VulkanError> {
|
) -> Result<(), VulkanError> {
|
||||||
zone!("record_draws");
|
zone!("record_draws");
|
||||||
let memory = &*self.memory.borrow();
|
let memory = &*self.memory.borrow();
|
||||||
let paint_regions = &memory.paint_regions[pass];
|
|
||||||
let pipelines = self.get_or_create_pipelines(target.format.vk_format, pass)?;
|
let pipelines = self.get_or_create_pipelines(target.format.vk_format, pass)?;
|
||||||
let dev = &self.device.device;
|
let dev = &self.device.device;
|
||||||
let mut current_pipeline = None;
|
let mut current_pipeline = None;
|
||||||
|
|
@ -697,33 +818,16 @@ impl VulkanRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for opt in opts {
|
for opt in &memory.ops[pass] {
|
||||||
match opt {
|
match opt {
|
||||||
GfxApiOpt::Sync => {}
|
VulkanOp::Fill(r) => {
|
||||||
GfxApiOpt::FillRect(r) => {
|
let pipeline = &pipelines.fill[r.source_type];
|
||||||
let push = FillPushConstants {
|
bind(pipeline);
|
||||||
pos: r.rect.to_points(),
|
for &pos in &memory.fill_targets[r.range.clone()] {
|
||||||
color: match pass {
|
let push = FillPushConstants {
|
||||||
RenderPass::BlendBuffer => {
|
pos,
|
||||||
r.color.to_array2(TransferFunction::Linear, r.alpha)
|
color: r.color,
|
||||||
}
|
};
|
||||||
RenderPass::FrameBuffer => {
|
|
||||||
r.color.to_array2(TransferFunction::Srgb, r.alpha)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let source_type = match push.color[3] < 1.0 {
|
|
||||||
true => TexSourceType::HasAlpha,
|
|
||||||
false => TexSourceType::Opaque,
|
|
||||||
};
|
|
||||||
let pipeline = &pipelines.fill[source_type];
|
|
||||||
for region in paint_regions {
|
|
||||||
let mut push = push;
|
|
||||||
let draw = region.constrain(&mut push.pos, None);
|
|
||||||
if !draw {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bind(pipeline);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
dev.cmd_push_constants(
|
dev.cmd_push_constants(
|
||||||
buf,
|
buf,
|
||||||
|
|
@ -736,65 +840,44 @@ impl VulkanRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GfxApiOpt::CopyTexture(c) => {
|
VulkanOp::Tex(c) => {
|
||||||
let tex = c.tex.as_vk(&self.device.device);
|
let tex = &c.tex;
|
||||||
if tex.contents_are_undefined.get() {
|
let pipeline = &pipelines.tex[c.copy_type][c.source_type];
|
||||||
log::warn!("Ignoring undefined texture");
|
bind(pipeline);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if tex.queue_state.get().acquire(QueueFamily::Gfx) == QueueTransfer::Impossible
|
|
||||||
{
|
|
||||||
log::warn!("Ignoring texture owned by different queue");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let copy_type = match c.alpha.is_some() {
|
|
||||||
true => TexCopyType::Multiply,
|
|
||||||
false => TexCopyType::Identity,
|
|
||||||
};
|
|
||||||
let source_type = match tex.format.has_alpha && !c.opaque {
|
|
||||||
true => TexSourceType::HasAlpha,
|
|
||||||
false => TexSourceType::Opaque,
|
|
||||||
};
|
|
||||||
let pipeline = &pipelines.tex[copy_type][source_type];
|
|
||||||
let push = TexPushConstants {
|
|
||||||
pos: c.target.to_points(),
|
|
||||||
tex_pos: c.source.to_points(),
|
|
||||||
alpha: c.alpha.unwrap_or_default(),
|
|
||||||
};
|
|
||||||
let image_info = DescriptorImageInfo::default()
|
let image_info = DescriptorImageInfo::default()
|
||||||
.image_view(tex.texture_view)
|
.image_view(tex.texture_view)
|
||||||
.image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL);
|
.image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL);
|
||||||
let init = Once::default();
|
if let Some(db) = &self.device.descriptor_buffer {
|
||||||
for region in paint_regions {
|
unsafe {
|
||||||
let mut push = push;
|
db.cmd_set_descriptor_buffer_offsets(
|
||||||
let draw = region.constrain(&mut push.pos, Some(&mut push.tex_pos));
|
buf,
|
||||||
if !draw {
|
PipelineBindPoint::GRAPHICS,
|
||||||
continue;
|
pipeline.pipeline_layout,
|
||||||
|
0,
|
||||||
|
&[0],
|
||||||
|
&[tex.descriptor_buffer_offset.get()],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
init.exec(|| unsafe {
|
} else {
|
||||||
bind(pipeline);
|
let write_descriptor_set = WriteDescriptorSet::default()
|
||||||
if let Some(db) = &self.device.descriptor_buffer {
|
.descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER)
|
||||||
db.cmd_set_descriptor_buffer_offsets(
|
.image_info(slice::from_ref(&image_info));
|
||||||
buf,
|
unsafe {
|
||||||
PipelineBindPoint::GRAPHICS,
|
self.device.push_descriptor.cmd_push_descriptor_set(
|
||||||
pipeline.pipeline_layout,
|
buf,
|
||||||
0,
|
PipelineBindPoint::GRAPHICS,
|
||||||
&[0],
|
pipeline.pipeline_layout,
|
||||||
&[tex.descriptor_buffer_offset.get()],
|
0,
|
||||||
);
|
slice::from_ref(&write_descriptor_set),
|
||||||
} else {
|
);
|
||||||
let write_descriptor_set = WriteDescriptorSet::default()
|
}
|
||||||
.descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER)
|
}
|
||||||
.image_info(slice::from_ref(&image_info));
|
for &[pos, tex_pos] in &memory.tex_targets[c.range.clone()] {
|
||||||
self.device.push_descriptor.cmd_push_descriptor_set(
|
let push = TexPushConstants {
|
||||||
buf,
|
pos,
|
||||||
PipelineBindPoint::GRAPHICS,
|
tex_pos,
|
||||||
pipeline.pipeline_layout,
|
alpha: c.alpha,
|
||||||
0,
|
};
|
||||||
slice::from_ref(&write_descriptor_set),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
unsafe {
|
unsafe {
|
||||||
dev.cmd_push_constants(
|
dev.cmd_push_constants(
|
||||||
buf,
|
buf,
|
||||||
|
|
@ -1430,23 +1513,24 @@ impl VulkanRenderer {
|
||||||
self.elide_blend_buffer(&mut blend_buffer);
|
self.elide_blend_buffer(&mut blend_buffer);
|
||||||
let bb = blend_buffer.as_deref();
|
let bb = blend_buffer.as_deref();
|
||||||
let buf = self.gfx_command_buffers.allocate()?;
|
let buf = self.gfx_command_buffers.allocate()?;
|
||||||
self.collect_memory(opts);
|
self.convert_ops(opts);
|
||||||
|
self.collect_memory();
|
||||||
self.begin_command_buffer(buf.buffer)?;
|
self.begin_command_buffer(buf.buffer)?;
|
||||||
self.create_descriptor_buffers(buf.buffer, opts, bb)?;
|
self.create_descriptor_buffers(buf.buffer, bb)?;
|
||||||
self.initial_barriers(buf.buffer, fb)?;
|
self.initial_barriers(buf.buffer, fb)?;
|
||||||
self.set_viewport(buf.buffer, fb);
|
self.set_viewport(buf.buffer, fb);
|
||||||
if let Some(bb) = bb {
|
if let Some(bb) = bb {
|
||||||
zone!("blend buffer pass");
|
zone!("blend buffer pass");
|
||||||
self.blend_buffer_initial_barrier(buf.buffer, bb);
|
self.blend_buffer_initial_barrier(buf.buffer, bb);
|
||||||
self.begin_rendering(buf.buffer, bb, clear, RenderPass::BlendBuffer);
|
self.begin_rendering(buf.buffer, bb, clear, RenderPass::BlendBuffer);
|
||||||
self.record_draws(buf.buffer, bb, opts, RenderPass::BlendBuffer)?;
|
self.record_draws(buf.buffer, bb, RenderPass::BlendBuffer)?;
|
||||||
self.end_rendering(buf.buffer);
|
self.end_rendering(buf.buffer);
|
||||||
self.blend_buffer_final_barrier(buf.buffer, bb);
|
self.blend_buffer_final_barrier(buf.buffer, bb);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
zone!("frame buffer pass");
|
zone!("frame buffer pass");
|
||||||
self.begin_rendering(buf.buffer, fb, clear, RenderPass::FrameBuffer);
|
self.begin_rendering(buf.buffer, fb, clear, RenderPass::FrameBuffer);
|
||||||
self.record_draws(buf.buffer, fb, opts, RenderPass::FrameBuffer)?;
|
self.record_draws(buf.buffer, fb, RenderPass::FrameBuffer)?;
|
||||||
if let Some(bb) = bb {
|
if let Some(bb) = bb {
|
||||||
self.blend_buffer_copy(buf.buffer, fb, bb)?;
|
self.blend_buffer_copy(buf.buffer, fb, bb)?;
|
||||||
}
|
}
|
||||||
|
|
@ -1581,7 +1665,7 @@ async fn await_release(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaintRegion {
|
impl PaintRegion {
|
||||||
fn constrain(&self, pos: &mut [[f32; 2]; 4], tex_pos: Option<&mut [[f32; 2]; 4]>) -> bool {
|
fn constrain(&self, pos: &mut Point, tex_pos: Option<&mut Point>) -> bool {
|
||||||
zone!("constrain");
|
zone!("constrain");
|
||||||
let mut npos = *pos;
|
let mut npos = *pos;
|
||||||
for [x, y] in &mut npos {
|
for [x, y] in &mut npos {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue