Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple crops #32

Merged
merged 7 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/libpisp/backend/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,16 @@ void BackEnd::GetGamma(pisp_be_gamma_config &gamma)

void BackEnd::SetCrop(pisp_be_crop_config const &crop)
{
be_config_extra_.crop = crop;
for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++)
be_config_extra_.crop[i] = crop;
be_config_extra_.dirty_flags_extra |= PISP_BE_DIRTY_CROP;
retile_ = true;
}

void BackEnd::SetCrop(unsigned int i, pisp_be_crop_config const &crop)
{
PISP_ASSERT(i < variant_.BackEndNumBranches(0));
be_config_extra_.crop[i] = crop;
be_config_extra_.dirty_flags_extra |= PISP_BE_DIRTY_CROP;
retile_ = true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/libpisp/backend/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class BackEnd final
void SetGamma(pisp_be_gamma_config const &gamma);
void GetGamma(pisp_be_gamma_config &gamma);
void SetCrop(pisp_be_crop_config const &crop);
void SetCrop(unsigned int i, pisp_be_crop_config const &crop);
void SetCsc(unsigned int i, pisp_be_ccm_config const &csc);
void GetCsc(unsigned int i, pisp_be_ccm_config &csc);
void SetOutputFormat(unsigned int i, pisp_be_output_format_config const &output_format);
Expand Down Expand Up @@ -155,7 +156,7 @@ class BackEnd final
pisp_be_cac_extra cac;
pisp_be_downscale_extra downscale[PISP_BACK_END_NUM_OUTPUTS];
pisp_be_resample_extra resample[PISP_BACK_END_NUM_OUTPUTS];
pisp_be_crop_config crop;
pisp_be_crop_config crop[PISP_BACK_END_NUM_OUTPUTS];
uint32_t dirty_flags_bayer; //these use pisp_be_bayer_enable
uint32_t dirty_flags_rgb; //use pisp_be_rgb_enable
uint32_t dirty_flags_extra; //these use pisp_be_dirty_t
Expand Down
45 changes: 23 additions & 22 deletions src/libpisp/backend/backend_prepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,9 @@ void BackEnd::finaliseConfig()
if (enabled)
{
// crop is enabled when it contains non-zero width/height
uint16_t w = be_config_extra_.crop.width ? be_config_extra_.crop.width
uint16_t w = be_config_extra_.crop[j].width ? be_config_extra_.crop[j].width
: be_config_.input_format.width;
uint16_t h = be_config_extra_.crop.width ? be_config_extra_.crop.height
uint16_t h = be_config_extra_.crop[j].width ? be_config_extra_.crop[j].height
: be_config_.input_format.height;

if (dirty_flags_rgb & PISP_BE_RGB_ENABLE_DOWNSCALE(j))
Expand Down Expand Up @@ -537,18 +537,18 @@ void BackEnd::updateSmartResize()
{
std::string filter;

// First get the size of the input to the rescalers. The crops are zero when not in use.
uint16_t input_width = be_config_extra_.crop.width;
if (!input_width)
input_width = be_config_.input_format.width;
uint16_t input_height = be_config_extra_.crop.height;
if (!input_height)
input_height = be_config_.input_format.height;

// Look through the output branches adjusting the scaling blocks where "smart resizing"
// has been requested.
for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++)
{
// First get the size of the input to the rescalers. The crops are zero when not in use.
uint16_t input_width = be_config_extra_.crop[i].width;
if (!input_width)
input_width = be_config_.input_format.width;
uint16_t input_height = be_config_extra_.crop[i].height;
if (!input_height)
input_height = be_config_.input_format.height;

if ((smart_resize_dirty_ & (1 << i)) || (be_config_extra_.dirty_flags_extra & PISP_BE_DIRTY_CROP))
{
if (smart_resize_[i].width && smart_resize_[i].height)
Expand Down Expand Up @@ -691,15 +691,16 @@ void BackEnd::updateTiles()
PISP_LOG(debug, "Input alignments are " << tiling_config.input_alignment << " pixels");

tiling_config.input_image_size = tiling::Length2(c.input_format.width, c.input_format.height);
tiling_config.crop = tiling::Interval2(tiling::Interval(ce.crop.offset_x, ce.crop.width),
tiling::Interval(ce.crop.offset_y, ce.crop.height));

if (tiling_config.crop.x.length == 0 || tiling_config.crop.y.length == 0)
tiling_config.crop = tiling::Interval2(tiling::Interval(0, c.input_format.width),
tiling::Interval(0, c.input_format.height));

for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++)
{
tiling_config.crop[i] = tiling::Interval2(tiling::Interval(ce.crop[i].offset_x, ce.crop[i].width),
tiling::Interval(ce.crop[i].offset_y, ce.crop[i].height));

if (tiling_config.crop[i].x.length == 0 || tiling_config.crop[i].y.length == 0)
tiling_config.crop[i] = tiling::Interval2(tiling::Interval(0, c.input_format.width),
tiling::Interval(0, c.input_format.height));

tiling_config.output_h_mirror[i] = be_config_.output_format[i].transform & PISP_BE_TRANSFORM_HFLIP;
tiling_config.downscale_factor[i] =
tiling::Length2(c.downscale[i].scale_factor_h, c.downscale[i].scale_factor_v);
Expand Down Expand Up @@ -794,25 +795,25 @@ std::vector<pisp_tile> BackEnd::retilePipeline(TilingConfig const &tiling_config
}

tiling::Crop2 downscale_crop;
tiling::Interval2 resample_size = tiles[i].crop.output;
tiling::Interval2 resample_size = tiles[i].crop[j].output;
resample_size.x = resample_size.x - tiles[i].resample[j].crop.x;
resample_size.y = resample_size.y - tiles[i].resample[j].crop.y;

// When a resize stage is disabled, the tile size after the stage is found from the input of the
// next block. Also there will be no extra crop necessary for the resize operation.
if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_DOWNSCALE(j))
{
downscale_crop = tiles[i].downscale[j].crop + tiles[i].crop.crop;
downscale_crop = tiles[i].downscale[j].crop + tiles[i].crop[j].crop;
// Size of the tile going into the resample block needs to be set here.
resample_size = tiles[i].downscale[j].output;
}
else if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_RESAMPLE(j))
{
downscale_crop = tiles[i].resample[j].crop + tiles[i].crop.crop;
downscale_crop = tiles[i].resample[j].crop + tiles[i].crop[j].crop;
}
else
{
downscale_crop = tiles[i].output[j].crop + tiles[i].crop.crop;
downscale_crop = tiles[i].output[j].crop + tiles[i].crop[j].crop;
}

t.crop_x_start[j] = downscale_crop.x.start;
Expand Down Expand Up @@ -952,8 +953,8 @@ void BackEnd::getOutputSize(int i, uint16_t *width, uint16_t *height, pisp_image
*width = be_config_extra_.resample[i].scaled_width, *height = be_config_extra_.resample[i].scaled_height;
else if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_DOWNSCALE(i))
*width = be_config_extra_.downscale[i].scaled_width, *height = be_config_extra_.downscale[i].scaled_height;
else if (be_config_extra_.crop.width) // crop width and height will be zero when crop disabled
*width = be_config_extra_.crop.width, *height = be_config_extra_.crop.height;
else if (be_config_extra_.crop[i].width) // crop width and height will be zero when crop disabled
*width = be_config_extra_.crop[i].width, *height = be_config_extra_.crop[i].height;
else
*width = ifmt.width, *height = ifmt.height;
}
Expand Down
32 changes: 31 additions & 1 deletion src/libpisp/backend/tiling/crop_stage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
using namespace tiling;

CropStage::CropStage(char const *name, Stage *upstream, Config const &config, int struct_offset)
: BasicStage(name, upstream->GetPipeline(), upstream, struct_offset), config_(config)
: BasicStage(name, upstream->GetPipeline(), upstream, struct_offset), config_(config), started_(false)
{
}

Expand All @@ -27,6 +27,11 @@ void CropStage::PushStartUp(int output_start, Dir dir)
PISP_LOG(debug, "(" << name_ << ") Enter with output_start " << output_start);

int input_start = output_start + config_.crop[dir].offset;
// input_start can never be negative here, but it is possible to have output_start
// negative if, for example, a branch starts producing output on the second
// tile in a row (or column) and the resampler requires left (or top) context pixels.
if (input_start < 0)
throw std::runtime_error("input start is negative: " + std::to_string(input_start));
output_interval_.offset = output_start;
input_interval_.offset = input_start;

Expand All @@ -39,6 +44,17 @@ int CropStage::PushEndDown(int input_end, Dir dir)
PISP_LOG(debug, "(" << name_ << ") Enter with input_end " << input_end);

int output_end = input_end - config_.crop[dir].offset;

// If negative, no output will be generated for this tile. Terminate the
// iteration here and don't go futher downstream.
if (output_end < 0)
{
PISP_LOG(debug, "(" << name_ << ") Output branch not started, terminating ");
return 0;
}

started_ = true;

if (output_end > config_.crop[dir].length)
output_end = config_.crop[dir].length;
input_interval_.SetEnd(input_end);
Expand All @@ -63,6 +79,15 @@ void CropStage::PushEndUp(int output_end, Dir dir)
void CropStage::PushCropDown(Interval interval, Dir dir)
{
PISP_LOG(debug, "(" << name_ << ") Enter with interval " << interval);

// Branch has not started producing output. Terminate the iteration here
// and don't go futher downstream.
if (!started_)
{
PISP_LOG(debug, "(" << name_ << ") Output branch not started, terminating ");
return;
}

PISP_ASSERT(interval > input_interval_);

input_interval_ = interval;
Expand All @@ -72,3 +97,8 @@ void CropStage::PushCropDown(Interval interval, Dir dir)
PISP_LOG(debug, "(" << name_ << ") Exit with interval " << output_interval_);
downstream_->PushCropDown(output_interval_, dir);
}

void CropStage::Reset()
{
started_ = false;
}
2 changes: 2 additions & 0 deletions src/libpisp/backend/tiling/crop_stage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class CropStage : public BasicStage
virtual int PushEndDown(int input_end, Dir dir);
virtual void PushEndUp(int output_end, Dir dir);
virtual void PushCropDown(Interval interval, Dir dir);
void Reset() override;

private:
Config config_;
bool started_;
};

} // namespace tiling
20 changes: 17 additions & 3 deletions src/libpisp/backend/tiling/output_stage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ using namespace tiling;
// the offset/length from the LH edge).

OutputStage::OutputStage(char const *name, Stage *upstream, Config const &config, int struct_offset)
: BasicStage(name, upstream->GetPipeline(), upstream, struct_offset), config_(config)
: BasicStage(name, upstream->GetPipeline(), upstream, struct_offset), config_(config), branch_complete_(false)
{
pipeline_->AddOutputStage(this);
}
Expand Down Expand Up @@ -118,7 +118,21 @@ void OutputStage::PushCropDown(Interval interval, [[maybe_unused]] Dir dir)
PISP_LOG(debug, "(" << name_ << ") Exit with interval " << output_interval_);
}

bool OutputStage::Done(Dir dir) const
void OutputStage::Reset()
{
return output_interval_.End() >= GetOutputImageSize()[dir];
BasicStage::Reset();
branch_complete_ = false;
}

bool OutputStage::BranchComplete() const
{
return branch_complete_;
}

bool OutputStage::Done(Dir dir)
{
if (output_interval_.End() >= GetOutputImageSize()[dir])
branch_complete_ = true;

return branch_complete_;
}
5 changes: 4 additions & 1 deletion src/libpisp/backend/tiling/output_stage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ class OutputStage : public BasicStage
virtual int PushEndDown(int input_end, Dir dir);
virtual void PushEndUp(int output_end, Dir dir);
virtual void PushCropDown(Interval interval, Dir dir);
bool Done(Dir dir) const;
virtual void Reset();
bool BranchComplete() const;
bool Done(Dir dir);

private:
Config config_;
bool branch_complete_;
};

} // namespace tiling
9 changes: 7 additions & 2 deletions src/libpisp/backend/tiling/pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

using namespace tiling;

Pipeline::Pipeline(char const *name, Config const &config) : name_(name), config_(config)
Pipeline::Pipeline(char const *name, Config const &config) : name_(name), config_(config), first_tile_(false)
{
}

Expand Down Expand Up @@ -74,13 +74,17 @@ int Pipeline::tileDirection(Dir dir, void *mem, size_t num_items, size_t item_si
reset();
bool done = false;
unsigned int num_tiles = 0;
first_tile_ = true;
for (; !done; num_tiles++)
{
PISP_LOG(debug, "----------------------------------------------------------------");
if (num_tiles == num_items)
throw std::runtime_error("Too many tiles!");
for (auto s : outputs_)
s->PushStartUp(s->GetOutputInterval().End(), dir);
{
if (!s->BranchComplete())
s->PushStartUp(s->GetOutputInterval().End(), dir);
}
for (auto s : inputs_)
s->PushEndDown(s->GetInputInterval().offset + config_.max_tile_size[dir], dir);
for (auto s : inputs_)
Expand All @@ -91,6 +95,7 @@ int Pipeline::tileDirection(Dir dir, void *mem, size_t num_items, size_t item_si
done = true;
for (auto s : outputs_)
done &= s->Done(dir);
first_tile_ = false;
}

PISP_LOG(debug, "Made " << num_tiles << " tiles in direction " << dir);
Expand Down
2 changes: 2 additions & 0 deletions src/libpisp/backend/tiling/pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Pipeline
void AddInputStage(InputStage *input_stage);
void AddOutputStage(OutputStage *output_stage);
void Tile(void *mem, size_t num_items, size_t item_size, Length2 *grid);
bool FirstTile() const { return first_tile_; }

private:
int tileDirection(Dir dir, void *mem, size_t num_items, size_t item_size);
Expand All @@ -46,6 +47,7 @@ class Pipeline
std::vector<Stage *> stages_;
std::vector<InputStage *> inputs_;
std::vector<OutputStage *> outputs_;
bool first_tile_;
};

} // namespace tiling
11 changes: 7 additions & 4 deletions src/libpisp/backend/tiling/pisp_tiling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@ void tile_pipeline(TilingConfig const &config, Tile *tiles, int num_tiles, Lengt
Length2(PipelineAlignX, PipelineAlignY));
ContextStage context_stage("context", &input_stage, context_config, offsetof(Tile, context));

CropStage::Config crop_config(config.crop);
CropStage crop_stage("crop", &context_stage, crop_config, offsetof(Tile, crop));

SplitStage split_stage("split", &crop_stage);
SplitStage split_stage("split", &context_stage);

std::unique_ptr<Stage> crop_stages[NumOutputBranches];
std::unique_ptr<Stage> downscale_stages[NumOutputBranches];
std::unique_ptr<Stage> resample_stages[NumOutputBranches];
std::unique_ptr<Stage> output_stages[NumOutputBranches];
Expand All @@ -74,6 +72,11 @@ void tile_pipeline(TilingConfig const &config, Tile *tiles, int num_tiles, Lengt
char name[32];
Stage *prev_stage = &split_stage;

sprintf(name, "crop%d", i);
crop_stages[i] = std::unique_ptr<Stage>(
new CropStage(name, prev_stage, config.crop[i], offsetof(Tile, crop) + i * sizeof(Region)));
prev_stage = crop_stages[i].get();

// There's a little awkwardness if the resize blocks (downscale and resample) are not enabled. Resize *does* change the output tile
// size, even if it's doing a 1-to-1 scaling (it loses context), so we must leave it out of the tiling
// calculation.
Expand Down
6 changes: 3 additions & 3 deletions src/libpisp/backend/tiling/pisp_tiling.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct Tile
tiling::Region input;
tiling::Region decompress;
tiling::Region context;
tiling::Region crop;
tiling::Region crop[NumOutputBranches];
tiling::Region downscale[NumOutputBranches];
tiling::Region resample[NumOutputBranches];
tiling::Region output[NumOutputBranches];
Expand All @@ -31,7 +31,7 @@ struct Tile
struct TilingConfig
{
tiling::Length2 input_image_size;
tiling::Interval2 crop;
tiling::Interval2 crop[NumOutputBranches];
tiling::Length2 downscale_image_size[NumOutputBranches];
tiling::Length2 output_image_size[NumOutputBranches];
tiling::Length2 max_tile_size;
Expand All @@ -51,9 +51,9 @@ inline std::ostream &operator<<(std::ostream &os, TilingConfig const &tc)
{
os << "TilingConfig:" << std::endl;
os << "\tinput_image_size " << tc.input_image_size << " align " << tc.input_alignment << std::endl;
os << "\tcrop " << tc.crop << std::endl;
for (int i = 0; i < NumOutputBranches; i++)
{
os << "\tcrop[" << i << "] " << tc.crop[i] << std::endl;
os << "\toutput_image_size[" << i << "] " << tc.output_image_size[i] << " align max "
<< tc.output_max_alignment[i] << " min " << tc.output_min_alignment[i] << std::endl;
os << "\tdownscale_image_size " << tc.downscale_image_size[i] << " downscale_factor " << tc.downscale_factor[i]
Expand Down
7 changes: 5 additions & 2 deletions src/libpisp/backend/tiling/rescale_stage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ void RescaleStage::PushStartUp(int output_start, Dir dir)
int input_start_P = output_start * config_.scale[dir];
int input_start = input_start_P >> config_.precision;
int input_start_w_context = input_start - config_.start_context[dir];

if (input_start_w_context < 0)
// input_start_w_context is allowed to go negative here if, for example, the branch starts producing output
// on the second tile in a row/column and the resampler requires left context pixels. In such cases, the left/top
// edge flag will not be set on the tile and the hardware cannot remove the left/top context pixels. So allow
// negative values on all but the left/top edge tile.
if (GetPipeline()->FirstTile() && input_start_w_context < 0)
input_start_w_context = 0;
output_interval_.offset = output_start;
input_interval_.offset = input_start_w_context;
Expand Down
Loading