mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
rsx: Implement stippled rendering
This commit is contained in:
parent
3df83e03a9
commit
1677618c75
15 changed files with 153 additions and 10 deletions
|
@ -430,6 +430,23 @@ namespace glsl
|
|||
"}\n\n";
|
||||
}
|
||||
|
||||
static void insert_rop_init(std::ostream& OS)
|
||||
{
|
||||
OS <<
|
||||
" if ((rop_control & (1u << 9)) != 0)\n"
|
||||
" {\n"
|
||||
" // Convert x,y to linear address\n"
|
||||
" uvec2 stipple_coord = uvec2(gl_FragCoord.xy) % uvec2(32u, 32u);\n"
|
||||
" uint address = stipple_coord.y * 32u + stipple_coord.x;\n"
|
||||
" uint mask = (1u << (address & 31u));\n\n"
|
||||
|
||||
" if ((stipple_pattern[address >> 7u][(address >> 5u) & 3u] & mask) == 0u)\n"
|
||||
" {\n"
|
||||
" _kill();\n"
|
||||
" }\n"
|
||||
" }\n\n";
|
||||
}
|
||||
|
||||
static void insert_rop(std::ostream& OS, const shader_properties& props)
|
||||
{
|
||||
const std::string reg0 = props.fp32_outputs ? "r0" : "h0";
|
||||
|
|
|
@ -190,6 +190,11 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
|||
OS << "{\n";
|
||||
OS << " sampler_info texture_parameters[16];\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
OS << "layout(std140, binding = " << GL_RASTERIZER_STATE_BIND_SLOT << ") uniform RasterizerHeap\n";
|
||||
OS << "{\n";
|
||||
OS << " uvec4 stipple_pattern[8];\n";
|
||||
OS << "};\n\n";
|
||||
}
|
||||
|
||||
void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
|
||||
|
@ -303,6 +308,8 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
|||
OS << "void main()\n";
|
||||
OS << "{\n";
|
||||
|
||||
::glsl::insert_rop_init(OS);
|
||||
|
||||
OS << "\n" << " fs_main();\n\n";
|
||||
|
||||
glsl::insert_rop(OS, m_shader_props);
|
||||
|
|
|
@ -200,6 +200,7 @@ void GLGSRender::on_init_thread()
|
|||
m_index_ring_buffer = std::make_unique<gl::legacy_ring_buffer>();
|
||||
m_vertex_instructions_buffer = std::make_unique<gl::legacy_ring_buffer>();
|
||||
m_fragment_instructions_buffer = std::make_unique<gl::legacy_ring_buffer>();
|
||||
m_raster_env_ring_buffer = std::make_unique<gl::legacy_ring_buffer>();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -213,6 +214,7 @@ void GLGSRender::on_init_thread()
|
|||
m_index_ring_buffer = std::make_unique<gl::ring_buffer>();
|
||||
m_vertex_instructions_buffer = std::make_unique<gl::ring_buffer>();
|
||||
m_fragment_instructions_buffer = std::make_unique<gl::ring_buffer>();
|
||||
m_raster_env_ring_buffer = std::make_unique<gl::ring_buffer>();
|
||||
}
|
||||
|
||||
m_attrib_ring_buffer->create(gl::buffer::target::texture, 256 * 0x100000);
|
||||
|
@ -223,6 +225,7 @@ void GLGSRender::on_init_thread()
|
|||
m_vertex_env_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
|
||||
m_texture_parameters_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
|
||||
m_vertex_layout_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
|
||||
m_raster_env_ring_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
|
||||
|
||||
if (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only)
|
||||
{
|
||||
|
@ -449,6 +452,11 @@ void GLGSRender::on_exit()
|
|||
m_fragment_instructions_buffer->remove();
|
||||
}
|
||||
|
||||
if (m_raster_env_ring_buffer)
|
||||
{
|
||||
m_raster_env_ring_buffer->remove();
|
||||
}
|
||||
|
||||
m_null_textures.clear();
|
||||
m_text_printer.close();
|
||||
m_gl_texture_cache.destroy();
|
||||
|
@ -704,6 +712,7 @@ void GLGSRender::load_program_env()
|
|||
const bool update_fragment_env = !!(m_graphics_state & rsx::pipeline_state::fragment_state_dirty);
|
||||
const bool update_fragment_texture_env = !!(m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty);
|
||||
const bool update_instruction_buffers = (!!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program));
|
||||
const bool update_raster_env = (rsx::method_registers.polygon_stipple_enabled() && !!(m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty));
|
||||
|
||||
m_program->use();
|
||||
|
||||
|
@ -714,6 +723,7 @@ void GLGSRender::load_program_env()
|
|||
if (update_fragment_texture_env) m_texture_parameters_buffer->reserve_storage_on_heap(256);
|
||||
if (update_fragment_constants) m_fragment_constants_buffer->reserve_storage_on_heap(align(fragment_constants_size, 256));
|
||||
if (update_transform_constants) m_transform_constants_buffer->reserve_storage_on_heap(8192);
|
||||
if (update_raster_env) m_raster_env_ring_buffer->reserve_storage_on_heap(128);
|
||||
|
||||
if (update_instruction_buffers)
|
||||
{
|
||||
|
@ -779,6 +789,16 @@ void GLGSRender::load_program_env()
|
|||
m_texture_parameters_buffer->bind_range(GL_FRAGMENT_TEXTURE_PARAMS_BIND_SLOT, mapping.second, 256);
|
||||
}
|
||||
|
||||
if (update_raster_env)
|
||||
{
|
||||
auto mapping = m_raster_env_ring_buffer->alloc_from_heap(128, m_uniform_buffer_offset_align);
|
||||
|
||||
std::memcpy(mapping.first, rsx::method_registers.polygon_stipple_pattern(), 128);
|
||||
m_raster_env_ring_buffer->bind_range(GL_RASTERIZER_STATE_BIND_SLOT, mapping.second, 128);
|
||||
|
||||
m_graphics_state &= ~(rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
||||
}
|
||||
|
||||
if (update_instruction_buffers)
|
||||
{
|
||||
if (m_interpreter_state & rsx::vertex_program_dirty)
|
||||
|
@ -830,6 +850,7 @@ void GLGSRender::load_program_env()
|
|||
if (update_fragment_texture_env) m_texture_parameters_buffer->unmap();
|
||||
if (update_fragment_constants) m_fragment_constants_buffer->unmap();
|
||||
if (update_transform_constants) m_transform_constants_buffer->unmap();
|
||||
if (update_raster_env) m_raster_env_ring_buffer->unmap();
|
||||
|
||||
if (update_instruction_buffers)
|
||||
{
|
||||
|
|
|
@ -99,6 +99,7 @@ private:
|
|||
std::unique_ptr<gl::ring_buffer> m_index_ring_buffer;
|
||||
std::unique_ptr<gl::ring_buffer> m_vertex_instructions_buffer;
|
||||
std::unique_ptr<gl::ring_buffer> m_fragment_instructions_buffer;
|
||||
std::unique_ptr<gl::ring_buffer> m_raster_env_ring_buffer;
|
||||
|
||||
// Identity buffer used to fix broken gl_VertexID on ATI stack
|
||||
std::unique_ptr<gl::buffer> m_identity_index_buffer;
|
||||
|
|
|
@ -28,9 +28,10 @@
|
|||
#define GL_FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 3
|
||||
#define GL_FRAGMENT_STATE_BIND_SLOT 4
|
||||
#define GL_FRAGMENT_TEXTURE_PARAMS_BIND_SLOT 5
|
||||
#define GL_INTERPRETER_VERTEX_BLOCK 6
|
||||
#define GL_INTERPRETER_FRAGMENT_BLOCK 7
|
||||
#define GL_COMPUTE_BUFFER_SLOT(index) (index + 8)
|
||||
#define GL_RASTERIZER_STATE_BIND_SLOT 6
|
||||
#define GL_INTERPRETER_VERTEX_BLOCK 7
|
||||
#define GL_INTERPRETER_FRAGMENT_BLOCK 8
|
||||
#define GL_COMPUTE_BUFFER_SLOT(index) (index + 9)
|
||||
|
||||
// Noop keyword outside of Windows (used in log_debug)
|
||||
#if !defined(_WIN32) && !defined(APIENTRY)
|
||||
|
|
|
@ -792,6 +792,11 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
if (rsx::method_registers.polygon_stipple_enabled())
|
||||
{
|
||||
rop_control |= (1u << 9);
|
||||
}
|
||||
|
||||
// Generate wpos coefficients
|
||||
// wpos equation is now as follows:
|
||||
// wpos.y = (frag_coord / resolution_scale) * ((window_origin!=top)?-1.: 1.) + ((window_origin!=top)? window_height : 0)
|
||||
|
|
|
@ -82,6 +82,9 @@ namespace rsx
|
|||
scissor_setup_invalid = 0x400, // Scissor configuration is broken
|
||||
scissor_setup_clipped = 0x800, // Scissor region is cropped by viewport constraint
|
||||
|
||||
polygon_stipple_pattern_dirty = 0x1000, // Rasterizer stippling pattern changed
|
||||
line_stipple_pattern_dirty = 0x2000, // Line stippling pattern changed
|
||||
|
||||
invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty,
|
||||
memory_barrier_bits = framebuffer_reads_dirty,
|
||||
all_dirty = ~0u
|
||||
|
|
|
@ -206,6 +206,11 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
|||
OS << " sampler_info texture_parameters[16];\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
OS << "layout(std140, set = 0, binding = " << std::to_string(m_binding_table.rasterizer_env_bind_slot) << ") uniform RasterizerHeap\n";
|
||||
OS << "{\n";
|
||||
OS << " uvec4 stipple_pattern[8];\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
vk::glsl::program_input in;
|
||||
in.location = m_binding_table.fragment_constant_buffers_bind_slot;
|
||||
in.domain = glsl::glsl_fragment_program;
|
||||
|
@ -220,6 +225,10 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
|||
in.location = m_binding_table.fragment_texture_params_bind_slot;
|
||||
in.name = "TextureParametersBuffer";
|
||||
inputs.push_back(in);
|
||||
|
||||
in.location = m_binding_table.rasterizer_env_bind_slot;
|
||||
in.name = "RasterizerHeap";
|
||||
inputs.push_back(in);
|
||||
}
|
||||
|
||||
void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
|
||||
|
@ -333,6 +342,8 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
|||
OS << "void main()\n";
|
||||
OS << "{\n";
|
||||
|
||||
::glsl::insert_rop_init(OS);
|
||||
|
||||
OS << "\n" << " fs_main();\n\n";
|
||||
|
||||
glsl::insert_rop(OS, m_shader_props);
|
||||
|
|
|
@ -279,6 +279,13 @@ namespace
|
|||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.rasterizer_env_bind_slot;
|
||||
|
||||
idx++;
|
||||
|
||||
for (auto binding = binding_table.textures_first_bind_slot;
|
||||
binding < binding_table.vertex_textures_first_bind_slot;
|
||||
binding++)
|
||||
|
@ -464,6 +471,7 @@ VKGSRender::VKGSRender() : GSRender()
|
|||
m_transform_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer");
|
||||
m_index_buffer_ring_info.create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_INDEX_RING_BUFFER_SIZE_M * 0x100000, "index buffer");
|
||||
m_texture_upload_buffer_ring_info.create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M * 0x100000, "texture upload buffer", 32 * 0x100000);
|
||||
m_raster_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "raster env buffer");
|
||||
|
||||
const auto shadermode = g_cfg.video.shadermode.get();
|
||||
|
||||
|
@ -473,6 +481,9 @@ VKGSRender::VKGSRender() : GSRender()
|
|||
m_fragment_instructions_buffer.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 64 * 0x100000, "fragment instructions buffer", 2048);
|
||||
}
|
||||
|
||||
// Initiailize optional allocation information with placeholders
|
||||
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, 128 };
|
||||
|
||||
const auto limits = m_device->gpu().get_limits();
|
||||
m_texbuffer_view_size = std::min(limits.maxTexelBufferElements, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000u);
|
||||
|
||||
|
@ -606,6 +617,7 @@ VKGSRender::~VKGSRender()
|
|||
m_texture_upload_buffer_ring_info.destroy();
|
||||
m_vertex_instructions_buffer.destroy();
|
||||
m_fragment_instructions_buffer.destroy();
|
||||
m_raster_env_ring_info.destroy();
|
||||
|
||||
//Fallback bindables
|
||||
null_buffer.reset();
|
||||
|
@ -806,7 +818,8 @@ void VKGSRender::check_heap_status(u32 flags)
|
|||
m_vertex_layout_ring_info.is_critical() ||
|
||||
m_fragment_constants_ring_info.is_critical() ||
|
||||
m_transform_constants_ring_info.is_critical() ||
|
||||
m_index_buffer_ring_info.is_critical();
|
||||
m_index_buffer_ring_info.is_critical() ||
|
||||
m_raster_env_ring_info.is_critical();
|
||||
}
|
||||
else if (flags)
|
||||
{
|
||||
|
@ -829,7 +842,7 @@ void VKGSRender::check_heap_status(u32 flags)
|
|||
heap_critical = m_vertex_env_ring_info.is_critical();
|
||||
break;
|
||||
case VK_HEAP_CHECK_FRAGMENT_ENV_STORAGE:
|
||||
heap_critical = m_fragment_env_ring_info.is_critical();
|
||||
heap_critical = m_fragment_env_ring_info.is_critical() || m_raster_env_ring_info.is_critical();
|
||||
break;
|
||||
case VK_HEAP_CHECK_TEXTURE_ENV_STORAGE:
|
||||
heap_critical = m_fragment_texture_params_ring_info.is_critical();
|
||||
|
@ -880,6 +893,7 @@ void VKGSRender::check_heap_status(u32 flags)
|
|||
m_transform_constants_ring_info.reset_allocation_stats();
|
||||
m_attrib_ring_info.reset_allocation_stats();
|
||||
m_texture_upload_buffer_ring_info.reset_allocation_stats();
|
||||
m_raster_env_ring_info.reset_allocation_stats();
|
||||
m_current_frame->reset_heap_ptrs();
|
||||
m_last_heap_sync_time = get_system_time();
|
||||
}
|
||||
|
@ -1652,6 +1666,7 @@ void VKGSRender::load_program_env()
|
|||
const bool update_fragment_env = !!(m_graphics_state & rsx::pipeline_state::fragment_state_dirty);
|
||||
const bool update_fragment_texture_env = !!(m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty);
|
||||
const bool update_instruction_buffers = (!!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program));
|
||||
const bool update_raster_env = (rsx::method_registers.polygon_stipple_enabled() && !!(m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty));
|
||||
|
||||
if (update_vertex_env)
|
||||
{
|
||||
|
@ -1731,6 +1746,20 @@ void VKGSRender::load_program_env()
|
|||
m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, mem, 256 };
|
||||
}
|
||||
|
||||
if (update_raster_env)
|
||||
{
|
||||
check_heap_status(VK_HEAP_CHECK_FRAGMENT_ENV_STORAGE);
|
||||
|
||||
auto mem = m_raster_env_ring_info.alloc<256>(256);
|
||||
auto buf = m_raster_env_ring_info.map(mem, 128);
|
||||
|
||||
std::memcpy(buf, rsx::method_registers.polygon_stipple_pattern(), 128);
|
||||
m_raster_env_ring_info.unmap();
|
||||
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, mem, 128 };
|
||||
|
||||
m_graphics_state &= ~(rsx::pipeline_state::polygon_stipple_pattern_dirty);
|
||||
}
|
||||
|
||||
if (update_instruction_buffers)
|
||||
{
|
||||
if (m_interpreter_state & rsx::vertex_program_dirty)
|
||||
|
@ -1778,6 +1807,7 @@ void VKGSRender::load_program_env()
|
|||
m_program->bind_uniform(m_vertex_constants_buffer_info, binding_table.vertex_constant_buffers_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_fragment_env_buffer_info, binding_table.fragment_state_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_fragment_texture_params_buffer_info, binding_table.fragment_texture_params_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_raster_env_buffer_info, binding_table.rasterizer_env_bind_slot, m_current_frame->descriptor_set);
|
||||
|
||||
if (!m_shader_interpreter.is_interpreter(m_program))
|
||||
{
|
||||
|
@ -1869,7 +1899,8 @@ void VKGSRender::close_and_submit_command_buffer(vk::fence* pFence, VkSemaphore
|
|||
m_fragment_constants_ring_info.dirty() ||
|
||||
m_index_buffer_ring_info.dirty() ||
|
||||
m_transform_constants_ring_info.dirty() ||
|
||||
m_texture_upload_buffer_ring_info.dirty())
|
||||
m_texture_upload_buffer_ring_info.dirty() ||
|
||||
m_raster_env_ring_info.dirty())
|
||||
{
|
||||
std::lock_guard lock(m_secondary_cb_guard);
|
||||
m_secondary_command_buffer.begin();
|
||||
|
@ -1883,6 +1914,7 @@ void VKGSRender::close_and_submit_command_buffer(vk::fence* pFence, VkSemaphore
|
|||
m_index_buffer_ring_info.sync(m_secondary_command_buffer);
|
||||
m_transform_constants_ring_info.sync(m_secondary_command_buffer);
|
||||
m_texture_upload_buffer_ring_info.sync(m_secondary_command_buffer);
|
||||
m_raster_env_ring_info.sync(m_secondary_command_buffer);
|
||||
|
||||
m_secondary_command_buffer.end();
|
||||
|
||||
|
|
|
@ -208,6 +208,7 @@ namespace vk
|
|||
s64 frag_texparam_heap_ptr = 0;
|
||||
s64 index_heap_ptr = 0;
|
||||
s64 texture_upload_heap_ptr = 0;
|
||||
s64 rasterizer_env_heap_ptr = 0;
|
||||
|
||||
u64 last_frame_sync_time = 0;
|
||||
|
||||
|
@ -230,6 +231,7 @@ namespace vk
|
|||
vtx_const_heap_ptr = other.vtx_const_heap_ptr;
|
||||
index_heap_ptr = other.index_heap_ptr;
|
||||
texture_upload_heap_ptr = other.texture_upload_heap_ptr;
|
||||
rasterizer_env_heap_ptr = other.rasterizer_env_heap_ptr;
|
||||
}
|
||||
|
||||
//Exchange storage (non-copyable)
|
||||
|
@ -238,7 +240,10 @@ namespace vk
|
|||
std::swap(buffer_views_to_clean, other.buffer_views_to_clean);
|
||||
}
|
||||
|
||||
void tag_frame_end(s64 attrib_loc, s64 vtxenv_loc, s64 fragenv_loc, s64 vtxlayout_loc, s64 fragtex_loc, s64 fragconst_loc,s64 vtxconst_loc, s64 index_loc, s64 texture_loc)
|
||||
void tag_frame_end(
|
||||
s64 attrib_loc, s64 vtxenv_loc, s64 fragenv_loc, s64 vtxlayout_loc,
|
||||
s64 fragtex_loc, s64 fragconst_loc,s64 vtxconst_loc, s64 index_loc,
|
||||
s64 texture_loc, s64 rasterizer_loc)
|
||||
{
|
||||
attrib_heap_ptr = attrib_loc;
|
||||
vtx_env_heap_ptr = vtxenv_loc;
|
||||
|
@ -249,6 +254,7 @@ namespace vk
|
|||
vtx_const_heap_ptr = vtxconst_loc;
|
||||
index_heap_ptr = index_loc;
|
||||
texture_upload_heap_ptr = texture_loc;
|
||||
rasterizer_env_heap_ptr = rasterizer_loc;
|
||||
|
||||
last_frame_sync_time = get_system_time();
|
||||
}
|
||||
|
@ -425,6 +431,7 @@ private:
|
|||
vk::data_heap m_vertex_layout_ring_info; // Vertex layout structure
|
||||
vk::data_heap m_index_buffer_ring_info; // Index data
|
||||
vk::data_heap m_texture_upload_buffer_ring_info; // Texture upload heap
|
||||
vk::data_heap m_raster_env_ring_info; // Raster control such as polygon and line stipple
|
||||
|
||||
vk::data_heap m_fragment_instructions_buffer;
|
||||
vk::data_heap m_vertex_instructions_buffer;
|
||||
|
@ -435,6 +442,7 @@ private:
|
|||
VkDescriptorBufferInfo m_vertex_constants_buffer_info;
|
||||
VkDescriptorBufferInfo m_fragment_constants_buffer_info;
|
||||
VkDescriptorBufferInfo m_fragment_texture_params_buffer_info;
|
||||
VkDescriptorBufferInfo m_raster_env_buffer_info;
|
||||
|
||||
VkDescriptorBufferInfo m_vertex_instructions_buffer_info;
|
||||
VkDescriptorBufferInfo m_fragment_instructions_buffer_info;
|
||||
|
|
|
@ -245,8 +245,9 @@ namespace vk
|
|||
u8 fragment_texture_params_bind_slot = 4;
|
||||
u8 vertex_buffers_first_bind_slot = 5;
|
||||
u8 conditional_render_predicate_slot = 8;
|
||||
u8 textures_first_bind_slot = 9;
|
||||
u8 vertex_textures_first_bind_slot = 9; // Invalid, has to be initialized properly
|
||||
u8 rasterizer_env_bind_slot = 9;
|
||||
u8 textures_first_bind_slot = 10;
|
||||
u8 vertex_textures_first_bind_slot = 10; // Invalid, has to be initialized properly
|
||||
u8 total_descriptor_bindings = vertex_textures_first_bind_slot; // Invalid, has to be initialized properly
|
||||
};
|
||||
|
||||
|
|
|
@ -122,7 +122,8 @@ void VKGSRender::advance_queued_frames()
|
|||
m_fragment_constants_ring_info.get_current_put_pos_minus_one(),
|
||||
m_transform_constants_ring_info.get_current_put_pos_minus_one(),
|
||||
m_index_buffer_ring_info.get_current_put_pos_minus_one(),
|
||||
m_texture_upload_buffer_ring_info.get_current_put_pos_minus_one());
|
||||
m_texture_upload_buffer_ring_info.get_current_put_pos_minus_one(),
|
||||
m_raster_env_ring_info.get_current_put_pos_minus_one());
|
||||
|
||||
m_queued_frames.push_back(m_current_frame);
|
||||
verify(HERE), m_queued_frames.size() <= VK_MAX_ASYNC_FRAMES;
|
||||
|
|
|
@ -4074,6 +4074,29 @@ struct registers_decoder<NV4097_SET_TRANSFORM_CONSTANT_LOAD>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct registers_decoder<NV4097_SET_POLYGON_STIPPLE>
|
||||
{
|
||||
struct decoded_type
|
||||
{
|
||||
private:
|
||||
u32 value;
|
||||
|
||||
public:
|
||||
decoded_type(u32 value) : value(value) {}
|
||||
|
||||
bool enabled() const
|
||||
{
|
||||
return value > 0;
|
||||
}
|
||||
};
|
||||
|
||||
static std::string dump(decoded_type&& decoded_values)
|
||||
{
|
||||
return std::string("polygon_stipple: ") + (decoded_values.enabled()? "true" : "false");
|
||||
}
|
||||
};
|
||||
|
||||
#define EXPAND_RANGE_1(index, MACRO) \
|
||||
MACRO(index)
|
||||
|
||||
|
|
|
@ -3120,6 +3120,8 @@ namespace rsx
|
|||
bind_range<NV4097_SET_VIEWPORT_OFFSET, 1, 3, nv4097::set_viewport_dirty_bit>();
|
||||
bind<NV4097_SET_INDEX_ARRAY_DMA, nv4097::check_index_array_dma>();
|
||||
bind<NV4097_SET_BLEND_EQUATION, nv4097::set_blend_equation>();
|
||||
bind<NV4097_SET_POLYGON_STIPPLE, nv4097::notify_state_changed<fragment_state_dirty>>();
|
||||
bind_array<NV4097_SET_POLYGON_STIPPLE, 1, 32, nv4097::notify_state_changed<polygon_stipple_pattern_dirty>>();
|
||||
|
||||
//NV308A (0xa400..0xbffc!)
|
||||
bind_range<NV308A_COLOR + (256 * 0), 1, 256, nv308a::color, 256 * 0>();
|
||||
|
|
|
@ -1706,6 +1706,16 @@ namespace rsx
|
|||
{
|
||||
return decode<NV4097_SET_POINT_SPRITE_CONTROL>().texcoord_mask();
|
||||
}
|
||||
|
||||
const void* polygon_stipple_pattern() const
|
||||
{
|
||||
return registers.data() + NV4097_SET_POLYGON_STIPPLE_PATTERN;
|
||||
}
|
||||
|
||||
bool polygon_stipple_enabled() const
|
||||
{
|
||||
return decode<NV4097_SET_POLYGON_STIPPLE>().enabled();
|
||||
}
|
||||
};
|
||||
|
||||
extern rsx_state method_registers;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue