if(!target)
throw invalid_operation("OpenGLCommands::clear");
+ if(!values)
+ return;
+
static Require _req(MSP_clear_buffer);
pipeline_state->apply();
vk.BeginCommandBuffer(current_buffer, begin_info);
}
-void VulkanCommands::begin_render_pass(const ClearValue *clear_values)
+void VulkanCommands::begin_render_pass(bool clear, const ClearValue *clear_values)
{
const Framebuffer *target = pipeline_state->get_framebuffer();
if(!target)
device.get_transfer_queue().dispatch_transfers(current_buffer);
// TODO Use proper value for to_present
- render_pass = device.get_pipeline_cache().get_render_pass(target->get_format(), clear_values, true);
+ VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(target->get_format(), clear, !clear_values, true);
target->refresh();
if(render_pass)
throw invalid_operation("VulkanCommands::clear");
- begin_render_pass(values);
+ begin_render_pass(true, values);
}
void VulkanCommands::draw(const Batch &batch)
const VulkanFunctions &vk = device.get_functions();
if(!render_pass)
- begin_render_pass(0);
+ begin_render_pass(false, 0);
pipeline_state->apply(current_buffer);
unsigned first_index = batch.get_offset()/batch.get_index_size();
~VulkanCommands();
void begin_buffer();
- void begin_render_pass(const ClearValue *);
+ void begin_render_pass(bool, const ClearValue *);
void end_render_pass();
void begin_frame(unsigned);
vk_attachments[i++] = a.tex->view_handle;
}
- VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(self.format, false, false);
+ VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(self.format, false, false, false);
VkFramebufferCreateInfo framebuffer_info = { };
framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
vk.DestroyDescriptorPool(descriptor_pool);
}
-VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool is_cleared, bool to_present)
+VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool clear, bool discard, bool to_present)
{
const VulkanFunctions &vk = device.get_functions();
- uint64_t key = hash<64>(static_cast<uint8_t>(is_cleared | (to_present*2)));
+ uint64_t key = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
for(FrameAttachment a: format)
key = hash_update<64>(key, a);
{
attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
attachments[i].samples = vk_samples;
- attachments[i].loadOp = (is_cleared ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
+ attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachments[i].initialLayout = (is_cleared ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ attachments[i].initialLayout = (clear ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
attachments[i].finalLayout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
unsigned attach_pt = get_attach_point(a);
PipelineCache(PipelineCache &&);
~PipelineCache();
- VkRenderPass get_render_pass(const FrameFormat &, bool, bool);
+ VkRenderPass get_render_pass(const FrameFormat &, bool, bool, bool);
VkPipeline get_pipeline(const PipelineState &);
VkDescriptorSet get_descriptor_set(const PipelineState &, unsigned);
};
const PipelineState &self = *static_cast<const PipelineState *>(this);
const FrameFormat &format = self.framebuffer->get_format();
- VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(format, false, false);
+ VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(format, false, false, false);
unsigned n_color_attachments = 0;
for(FrameAttachment a: format)
void set_object_lod_bias(unsigned);
unsigned get_object_lod_bias() const { return get_state().object_lod_bias; }
- void clear(const ClearValue *);
+ /** Clears framebuffer contents. If values is not null, it must contain one
+ element for each attachment. Otherwise the framebuffer contents are
+ discarded and become undefined. */
+ void clear(const ClearValue *values);
/** Draws a batch of primitives. A shader must be active. */
void draw(const Batch &);
{
unsigned j = i%2;
renderer.set_framebuffer(i+1<postproc.size() ? &target[1-j]->get_framebuffer() : out_fbo);
+ renderer.clear(0);
const Texture2D &color = target[j]->get_target_texture(COLOR_ATTACHMENT);
const Texture2D &depth = target[j]->get_target_texture(DEPTH_ATTACHMENT);
postproc[i]->render(renderer, color, depth);