update parallel rdp

This commit is contained in:
Logan McNaughton
2022-09-05 10:27:23 -06:00
parent ef40b5e17a
commit a2afcb3f77
5 changed files with 96 additions and 4 deletions
+1 -1
View File
@@ -1 +1 @@
e6cf0e5ca257135acbcacfbdacd7cd3fdf3fb408
07c3d161dbeb78121be5eebdab7c810b72af822a
@@ -227,6 +227,11 @@ bool CommandProcessor::device_is_supported() const
return is_supported;
}
void CommandProcessor::set_validation_interface(ValidationInterface *iface)
{
renderer.set_validation_interface(iface);
}
void CommandProcessor::clear_hidden_rdram()
{
clear_buffer(*hidden_rdram, 0x03030303);
@@ -124,6 +124,8 @@ public:
~CommandProcessor();
void set_validation_interface(ValidationInterface *iface);
bool device_is_supported() const;
// Synchronization.
@@ -210,10 +212,10 @@ private:
std::unique_ptr<ShaderBank> shader_bank;
#endif
CommandRing ring;
VideoInterface vi;
// Tear-down order is important here.
Renderer renderer;
VideoInterface vi;
CommandRing ring;
void clear_hidden_rdram();
void clear_tmem();
@@ -120,6 +120,11 @@ void Renderer::set_device(Vulkan::Device *device_)
device = device_;
}
void Renderer::set_validation_interface(ValidationInterface *iface)
{
validation_iface = iface;
}
bool Renderer::init_caps()
{
auto &features = device->get_device_features();
@@ -1404,8 +1409,50 @@ void Renderer::fixup_triangle_setup(TriangleSetup &setup) const
setup.flags |= TRIANGLE_SETUP_FILL_COPY_RASTER_BIT;
}
void Renderer::validate_draw_state() const
{
if ((stream.static_raster_state.flags & RASTERIZATION_FILL_BIT) != 0)
{
if (fb.fmt == FBFormat::I4)
{
validation_iface->report_rdp_crash(ValidationError::Fill4bpp,
"Attempted to use Fill mode on 4bpp surface.");
}
if ((stream.depth_blend_state.flags & DEPTH_BLEND_DEPTH_TEST_BIT) != 0)
{
validation_iface->report_rdp_crash(ValidationError::FillDepthTest,
"Attempted to use Fill mode with depth test.");
}
if ((stream.depth_blend_state.flags & DEPTH_BLEND_IMAGE_READ_ENABLE_BIT) != 0)
{
validation_iface->report_rdp_crash(ValidationError::FillImageReadEnable,
"Attempted to use Fill mode with image read enable.");
}
if ((stream.depth_blend_state.flags & DEPTH_BLEND_DEPTH_UPDATE_BIT) != 0 &&
!constants.use_prim_depth)
{
validation_iface->report_rdp_crash(ValidationError::FillDepthWrite,
"Attempted to use Fill mode with depth write enabled.");
}
}
else if ((stream.static_raster_state.flags & RASTERIZATION_COPY_BIT) != 0)
{
if (fb.fmt == FBFormat::RGBA8888)
{
validation_iface->report_rdp_crash(ValidationError::Copy32bpp,
"Attempted to use Copy mode on 32bpp surface.");
}
}
}
void Renderer::draw_shaded_primitive(TriangleSetup &setup, const AttributeSetup &attr)
{
if (validation_iface)
validate_draw_state();
fixup_triangle_setup(setup);
unsigned num_tiles = compute_conservative_max_num_tiles(setup);
@@ -3040,6 +3087,15 @@ bool Renderer::tmem_upload_needs_flush(uint32_t addr) const
void Renderer::load_tile(uint32_t tile, const LoadTileInfo &info)
{
if (validation_iface && info.mode == UploadMode::TLUT)
{
if ((info.thi >> 2) > (info.tlo >> 2))
{
validation_iface->report_rdp_crash(ValidationError::InvalidMultilineLoadTlut,
"Attempting to load multiple lines in TLUT.");
}
}
if (tmem_upload_needs_flush(info.tex_addr))
flush_queues();
@@ -3171,6 +3227,8 @@ void Renderer::load_tile_iteration(uint32_t tile, const LoadTileInfo &info, uint
if (info.size == TextureSize::Bpp4)
{
LOGE("4-bit VRAM pointer crashes the RDP.\n");
if (validation_iface)
validation_iface->report_rdp_crash(ValidationError::LoadTile4bpp, "4-bit VRAM pointer crashes the RDP.");
return;
}
@@ -72,6 +72,28 @@ struct RendererOptions
bool super_sampled_readback_dither = false;
};
enum class ValidationError
{
Fill4bpp,
LoadTile4bpp,
InvalidMultilineLoadTlut,
FillDepthTest,
FillDepthWrite,
FillImageReadEnable,
Copy32bpp
};
class ValidationInterface
{
public:
virtual ~ValidationInterface() = default;
// Validation errors may be called from a thread as errors are encountered.
// Reports situations that would cause fatal error on a real RDP.
// We only opt to report these situations rather than deliberately crashing the renderer.
// Handling crashes is only relevant during development of N64 homebrew.
virtual void report_rdp_crash(ValidationError err, const char *msg) = 0;
};
class Renderer : public Vulkan::DebugChannelInterface
{
public:
@@ -79,6 +101,8 @@ public:
~Renderer();
void set_device(Vulkan::Device *device);
void set_validation_interface(ValidationInterface *iface);
// If coherent is false, RDRAM is a buffer split into data in lower half and writemask state in upper half, each part being size large.
// offset must be 0 in this case.
void set_rdram(Vulkan::Buffer *buffer, uint8_t *host_rdram, size_t offset, size_t size, bool coherent);
@@ -136,11 +160,14 @@ private:
CommandProcessor &processor;
Vulkan::Device *device = nullptr;
Vulkan::Buffer *rdram = nullptr;
ValidationInterface *validation_iface = nullptr;
Vulkan::BufferHandle upscaling_reference_rdram;
Vulkan::BufferHandle upscaling_multisampled_rdram;
Vulkan::BufferHandle upscaling_multisampled_hidden_rdram;
void validate_draw_state() const;
struct
{
uint8_t *host_rdram = nullptr;