Merge pull request #1865 from vlj/rsx-refactor

Factorize rsx state
This commit is contained in:
vlj 2016-07-07 22:49:23 +02:00 committed by GitHub
commit dcb3169f56
31 changed files with 2662 additions and 1199 deletions

View File

@ -347,16 +347,16 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
template<typename T>
std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
EXPECTS(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
EXPECTS(rsx::method_registers.vertex_data_base_index() == 0);
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u32 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
@ -403,12 +403,12 @@ std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u32 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
@ -426,12 +426,12 @@ std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, g
std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
u32 address = rsx::get_address(rsx::method_registers.index_array_address(), rsx::method_registers.index_array_location());
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
u16 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
bool is_primitive_restart_enabled = rsx::method_registers.restart_index_enabled();
u16 primitive_restart_index = rsx::method_registers.restart_index();
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)

View File

@ -141,19 +141,16 @@ namespace rsx
template <typename ...Args>
void prepare_render_target(
command_list_type command_list,
u32 set_surface_format_reg,
surface_color_format color_format, surface_depth_format depth_format,
u32 clip_horizontal_reg, u32 clip_vertical_reg,
surface_target set_surface_target,
const std::array<u32, 4> &surface_addresses, u32 address_z,
Args&&... extra_params)
{
u32 clip_width = clip_horizontal_reg >> 16;
u32 clip_height = clip_vertical_reg >> 16;
u32 clip_x = clip_horizontal_reg;
u32 clip_y = clip_vertical_reg;
surface_color_format color_format = to_surface_color_format(set_surface_format_reg & 0x1f);
surface_depth_format depth_format = to_surface_depth_format((set_surface_format_reg >> 5) & 0x7);
u32 clip_width = clip_horizontal_reg;
u32 clip_height = clip_vertical_reg;
// u32 clip_x = clip_horizontal_reg;
// u32 clip_y = clip_vertical_reg;
// Make previous RTTs sampleable
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)

View File

@ -77,8 +77,8 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
u32 vertex_count = get_vertex_count(vertex_ranges);
size_t offset_in_vertex_buffers_buffer = 0;
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
EXPECTS(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
u32 input_mask = rsx::method_registers.vertex_attrib_input_mask();
EXPECTS(rsx::method_registers.vertex_data_base_index() == 0);
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
@ -86,17 +86,17 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
if (!enabled)
continue;
if (vertex_arrays_info[index].size > 0)
if (rsx::method_registers.vertex_arrays_info[index].size > 0)
{
// Active vertex array
const rsx::data_array_format_info &info = vertex_arrays_info[index];
const rsx::data_array_format_info &info = rsx::method_registers.vertex_arrays_info[index];
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
UINT buffer_size = element_size * vertex_count;
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 base_offset = rsx::method_registers.vertex_data_base_offset();
u32 offset = rsx::method_registers.vertex_arrays_info[index].offset();
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address));
@ -117,11 +117,11 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
m_timers.buffer_upload_size += buffer_size;
}
else if (register_vertex_info[index].size > 0)
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
// In register vertex attribute
const rsx::data_array_format_info &info = register_vertex_info[index];
const std::vector<u8> &data = register_vertex_data[index];
const rsx::data_array_format_info &info = rsx::method_registers.register_vertex_info[index];
const std::vector<u8> &data = rsx::method_registers.register_vertex_data[index];
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
UINT buffer_size = gsl::narrow<UINT>(data.size());
@ -224,13 +224,15 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
// Separate constant buffer
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 256));
fill_scale_offset_data(mapped_buffer);
int is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]);
u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF);
int is_alpha_tested = rsx::method_registers.alpha_test_enabled();
u8 alpha_ref_raw = rsx::method_registers.alpha_ref();
float alpha_ref = alpha_ref_raw / 255.f;
memcpy((char*)mapped_buffer + 16 * sizeof(float), &is_alpha_tested, sizeof(int));
memcpy((char*)mapped_buffer + 17 * sizeof(float), &alpha_ref, sizeof(float));
memcpy((char*)mapped_buffer + 18 * sizeof(float), &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float));
memcpy((char*)mapped_buffer + 19 * sizeof(float), &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float));
f32 fogp0 = rsx::method_registers.fog_params_0();
f32 fogp1 = rsx::method_registers.fog_params_1();
memcpy((char*)mapped_buffer + 18 * sizeof(float), &fogp0, sizeof(float));
memcpy((char*)mapped_buffer + 19 * sizeof(float), &fogp1, sizeof(float));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256));
@ -321,7 +323,7 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
size_t vertex_count;
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_view;
std::tie(vertex_buffer_view, vertex_count) = upload_inlined_vertex_array(
vertex_arrays_info,
rsx::method_registers.vertex_arrays_info,
{ (const gsl::byte*) inline_vertex_array.data(), gsl::narrow<int>(inline_vertex_array.size() * sizeof(uint)) },
m_buffer_data, m_vertex_buffer_data.Get(), command_list);
@ -355,7 +357,7 @@ std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRe
// Index count
size_t index_count = get_index_count(draw_mode, gsl::narrow<int>(get_vertex_count(first_count_commands)));
rsx::index_array_type indexed_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
rsx::index_array_type indexed_type = rsx::method_registers.index_type();
size_t index_size = get_index_type_size(indexed_type);
// Alloc

View File

@ -6,79 +6,79 @@
#include "Emu/RSX/GCM.h"
D3D12_BLEND_OP get_blend_op(u16 op)
D3D12_BLEND_OP get_blend_op(rsx::blend_equation op)
{
switch (op)
{
case CELL_GCM_FUNC_ADD: return D3D12_BLEND_OP_ADD;
case CELL_GCM_FUNC_SUBTRACT: return D3D12_BLEND_OP_SUBTRACT;
case CELL_GCM_FUNC_REVERSE_SUBTRACT: return D3D12_BLEND_OP_REV_SUBTRACT;
case CELL_GCM_MIN: return D3D12_BLEND_OP_MIN;
case CELL_GCM_MAX: return D3D12_BLEND_OP_MAX;
case CELL_GCM_FUNC_ADD_SIGNED:
case CELL_GCM_FUNC_REVERSE_ADD_SIGNED:
case CELL_GCM_FUNC_REVERSE_SUBTRACT_SIGNED:
case rsx::blend_equation::add: return D3D12_BLEND_OP_ADD;
case rsx::blend_equation::substract: return D3D12_BLEND_OP_SUBTRACT;
case rsx::blend_equation::reverse_substract: return D3D12_BLEND_OP_REV_SUBTRACT;
case rsx::blend_equation::min: return D3D12_BLEND_OP_MIN;
case rsx::blend_equation::max: return D3D12_BLEND_OP_MAX;
case rsx::blend_equation::add_signed:
case rsx::blend_equation::reverse_add_signed:
case rsx::blend_equation::reverse_substract_signed:
break;
}
throw EXCEPTION("Invalid or unsupported blend op (0x%x)", op);
}
D3D12_BLEND get_blend_factor(u16 factor)
D3D12_BLEND get_blend_factor(rsx::blend_factor factor)
{
switch (factor)
{
case CELL_GCM_ZERO: return D3D12_BLEND_ZERO;
case CELL_GCM_ONE: return D3D12_BLEND_ONE;
case CELL_GCM_SRC_COLOR: return D3D12_BLEND_SRC_COLOR;
case CELL_GCM_ONE_MINUS_SRC_COLOR: return D3D12_BLEND_INV_SRC_COLOR;
case CELL_GCM_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA;
case CELL_GCM_ONE_MINUS_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA;
case CELL_GCM_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA;
case CELL_GCM_ONE_MINUS_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA;
case CELL_GCM_DST_COLOR: return D3D12_BLEND_DEST_COLOR;
case CELL_GCM_ONE_MINUS_DST_COLOR: return D3D12_BLEND_INV_DEST_COLOR;
case CELL_GCM_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT;
case CELL_GCM_CONSTANT_COLOR:
case CELL_GCM_CONSTANT_ALPHA:
case rsx::blend_factor::zero: return D3D12_BLEND_ZERO;
case rsx::blend_factor::one: return D3D12_BLEND_ONE;
case rsx::blend_factor::src_color: return D3D12_BLEND_SRC_COLOR;
case rsx::blend_factor::one_minus_src_color: return D3D12_BLEND_INV_SRC_COLOR;
case rsx::blend_factor::src_alpha: return D3D12_BLEND_SRC_ALPHA;
case rsx::blend_factor::one_minus_src_alpha: return D3D12_BLEND_INV_SRC_ALPHA;
case rsx::blend_factor::dst_alpha: return D3D12_BLEND_DEST_ALPHA;
case rsx::blend_factor::one_minus_dst_alpha: return D3D12_BLEND_INV_DEST_ALPHA;
case rsx::blend_factor::dst_color: return D3D12_BLEND_DEST_COLOR;
case rsx::blend_factor::one_minus_dst_color: return D3D12_BLEND_INV_DEST_COLOR;
case rsx::blend_factor::src_alpha_saturate: return D3D12_BLEND_SRC_ALPHA_SAT;
case rsx::blend_factor::constant_color:
case rsx::blend_factor::constant_alpha:
{
LOG_ERROR(RSX,"Constant blend factor not supported. Using ONE instead");
LOG_ERROR(RSX, "Constant blend factor not supported. Using ONE instead");
return D3D12_BLEND_ONE;
}
case CELL_GCM_ONE_MINUS_CONSTANT_COLOR:
case CELL_GCM_ONE_MINUS_CONSTANT_ALPHA:
case rsx::blend_factor::one_minus_constant_color:
case rsx::blend_factor::one_minus_constant_alpha:
{
LOG_ERROR(RSX,"Inv Constant blend factor not supported. Using ZERO instead");
LOG_ERROR(RSX, "Inv Constant blend factor not supported. Using ZERO instead");
return D3D12_BLEND_ZERO;
}
}
throw EXCEPTION("Invalid blend factor (0x%x)", factor);
}
D3D12_BLEND get_blend_factor_alpha(u16 factor)
D3D12_BLEND get_blend_factor_alpha(rsx::blend_factor factor)
{
switch (factor)
{
case CELL_GCM_ZERO: return D3D12_BLEND_ZERO;
case CELL_GCM_ONE: return D3D12_BLEND_ONE;
case CELL_GCM_SRC_COLOR: return D3D12_BLEND_SRC_ALPHA;
case CELL_GCM_ONE_MINUS_SRC_COLOR: return D3D12_BLEND_INV_SRC_ALPHA;
case CELL_GCM_SRC_ALPHA: return D3D12_BLEND_SRC_ALPHA;
case CELL_GCM_ONE_MINUS_SRC_ALPHA: return D3D12_BLEND_INV_SRC_ALPHA;
case CELL_GCM_DST_ALPHA: return D3D12_BLEND_DEST_ALPHA;
case CELL_GCM_ONE_MINUS_DST_ALPHA: return D3D12_BLEND_INV_DEST_ALPHA;
case CELL_GCM_DST_COLOR: return D3D12_BLEND_DEST_ALPHA;
case CELL_GCM_ONE_MINUS_DST_COLOR: return D3D12_BLEND_INV_DEST_ALPHA;
case CELL_GCM_SRC_ALPHA_SATURATE: return D3D12_BLEND_SRC_ALPHA_SAT;
case CELL_GCM_CONSTANT_COLOR:
case CELL_GCM_CONSTANT_ALPHA:
case rsx::blend_factor::zero: return D3D12_BLEND_ZERO;
case rsx::blend_factor::one: return D3D12_BLEND_ONE;
case rsx::blend_factor::src_color: return D3D12_BLEND_SRC_ALPHA;
case rsx::blend_factor::one_minus_src_color: return D3D12_BLEND_INV_SRC_ALPHA;
case rsx::blend_factor::src_alpha: return D3D12_BLEND_SRC_ALPHA;
case rsx::blend_factor::one_minus_src_alpha: return D3D12_BLEND_INV_SRC_ALPHA;
case rsx::blend_factor::dst_alpha: return D3D12_BLEND_DEST_ALPHA;
case rsx::blend_factor::one_minus_dst_alpha: return D3D12_BLEND_INV_DEST_ALPHA;
case rsx::blend_factor::dst_color: return D3D12_BLEND_DEST_ALPHA;
case rsx::blend_factor::one_minus_dst_color: return D3D12_BLEND_INV_DEST_ALPHA;
case rsx::blend_factor::src_alpha_saturate: return D3D12_BLEND_SRC_ALPHA_SAT;
case rsx::blend_factor::constant_color:
case rsx::blend_factor::constant_alpha:
{
LOG_ERROR(RSX,"Constant blend factor not supported. Using ONE instead");
LOG_ERROR(RSX, "Constant blend factor not supported. Using ONE instead");
return D3D12_BLEND_ONE;
}
case CELL_GCM_ONE_MINUS_CONSTANT_COLOR:
case CELL_GCM_ONE_MINUS_CONSTANT_ALPHA:
case rsx::blend_factor::one_minus_constant_color:
case rsx::blend_factor::one_minus_constant_alpha:
{
LOG_ERROR(RSX,"Inv Constant blend factor not supported. Using ZERO instead");
LOG_ERROR(RSX, "Inv Constant blend factor not supported. Using ZERO instead");
return D3D12_BLEND_ZERO;
}
}
@ -88,25 +88,25 @@ D3D12_BLEND get_blend_factor_alpha(u16 factor)
/**
* Convert GCM logic op code to D3D12 one
*/
D3D12_LOGIC_OP get_logic_op(u32 op)
D3D12_LOGIC_OP get_logic_op(rsx::logic_op op)
{
switch (op)
{
case CELL_GCM_CLEAR: return D3D12_LOGIC_OP_CLEAR;
case CELL_GCM_AND: return D3D12_LOGIC_OP_AND;
case CELL_GCM_AND_REVERSE: return D3D12_LOGIC_OP_AND_REVERSE;
case CELL_GCM_COPY: return D3D12_LOGIC_OP_COPY;
case CELL_GCM_AND_INVERTED: return D3D12_LOGIC_OP_AND_INVERTED;
case CELL_GCM_NOOP: return D3D12_LOGIC_OP_NOOP;
case CELL_GCM_XOR: return D3D12_LOGIC_OP_XOR;
case CELL_GCM_OR: return D3D12_LOGIC_OP_OR;
case CELL_GCM_NOR: return D3D12_LOGIC_OP_NOR;
case CELL_GCM_EQUIV: return D3D12_LOGIC_OP_EQUIV;
case CELL_GCM_INVERT: return D3D12_LOGIC_OP_INVERT;
case CELL_GCM_OR_REVERSE: return D3D12_LOGIC_OP_OR_REVERSE;
case CELL_GCM_COPY_INVERTED: return D3D12_LOGIC_OP_COPY_INVERTED;
case CELL_GCM_OR_INVERTED: return D3D12_LOGIC_OP_OR_INVERTED;
case CELL_GCM_NAND: return D3D12_LOGIC_OP_NAND;
case rsx::logic_op::logic_clear: return D3D12_LOGIC_OP_CLEAR;
case rsx::logic_op::logic_and: return D3D12_LOGIC_OP_AND;
case rsx::logic_op::logic_and_reverse: return D3D12_LOGIC_OP_AND_REVERSE;
case rsx::logic_op::logic_copy: return D3D12_LOGIC_OP_COPY;
case rsx::logic_op::logic_and_inverted: return D3D12_LOGIC_OP_AND_INVERTED;
case rsx::logic_op::logic_noop: return D3D12_LOGIC_OP_NOOP;
case rsx::logic_op::logic_xor: return D3D12_LOGIC_OP_XOR;
case rsx::logic_op::logic_or: return D3D12_LOGIC_OP_OR;
case rsx::logic_op::logic_nor: return D3D12_LOGIC_OP_NOR;
case rsx::logic_op::logic_equiv: return D3D12_LOGIC_OP_EQUIV;
case rsx::logic_op::logic_invert: return D3D12_LOGIC_OP_INVERT;
case rsx::logic_op::logic_or_reverse: return D3D12_LOGIC_OP_OR_REVERSE;
case rsx::logic_op::logic_copy_inverted: return D3D12_LOGIC_OP_COPY_INVERTED;
case rsx::logic_op::logic_or_inverted: return D3D12_LOGIC_OP_OR_INVERTED;
case rsx::logic_op::logic_nand: return D3D12_LOGIC_OP_NAND;
}
throw EXCEPTION("Invalid logic op (0x%x)", op);
}
@ -114,34 +114,34 @@ D3D12_LOGIC_OP get_logic_op(u32 op)
/**
* Convert GCM stencil op code to D3D12 one
*/
D3D12_STENCIL_OP get_stencil_op(u32 op)
D3D12_STENCIL_OP get_stencil_op(rsx::stencil_op op)
{
switch (op)
{
case CELL_GCM_KEEP: return D3D12_STENCIL_OP_KEEP;
case CELL_GCM_ZERO: return D3D12_STENCIL_OP_ZERO;
case CELL_GCM_REPLACE: return D3D12_STENCIL_OP_REPLACE;
case CELL_GCM_INCR: return D3D12_STENCIL_OP_INCR_SAT;
case CELL_GCM_DECR: return D3D12_STENCIL_OP_DECR_SAT;
case CELL_GCM_INVERT: return D3D12_STENCIL_OP_INVERT;
case CELL_GCM_INCR_WRAP: return D3D12_STENCIL_OP_INCR;
case CELL_GCM_DECR_WRAP: return D3D12_STENCIL_OP_DECR;
case rsx::stencil_op::keep: return D3D12_STENCIL_OP_KEEP;
case rsx::stencil_op::zero: return D3D12_STENCIL_OP_ZERO;
case rsx::stencil_op::replace: return D3D12_STENCIL_OP_REPLACE;
case rsx::stencil_op::incr: return D3D12_STENCIL_OP_INCR_SAT;
case rsx::stencil_op::decr: return D3D12_STENCIL_OP_DECR_SAT;
case rsx::stencil_op::invert: return D3D12_STENCIL_OP_INVERT;
case rsx::stencil_op::incr_wrap: return D3D12_STENCIL_OP_INCR;
case rsx::stencil_op::decr_wrap: return D3D12_STENCIL_OP_DECR;
}
throw EXCEPTION("Invalid stencil op (0x%x)", op);
}
D3D12_COMPARISON_FUNC get_compare_func(u32 op)
D3D12_COMPARISON_FUNC get_compare_func(rsx::comparaison_function op)
{
switch (op)
{
case CELL_GCM_NEVER: return D3D12_COMPARISON_FUNC_NEVER;
case CELL_GCM_LESS: return D3D12_COMPARISON_FUNC_LESS;
case CELL_GCM_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL;
case CELL_GCM_LEQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
case CELL_GCM_GREATER: return D3D12_COMPARISON_FUNC_GREATER;
case CELL_GCM_NOTEQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
case CELL_GCM_GEQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
case CELL_GCM_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS;
case rsx::comparaison_function::never: return D3D12_COMPARISON_FUNC_NEVER;
case rsx::comparaison_function::less: return D3D12_COMPARISON_FUNC_LESS;
case rsx::comparaison_function::equal: return D3D12_COMPARISON_FUNC_EQUAL;
case rsx::comparaison_function::less_or_equal: return D3D12_COMPARISON_FUNC_LESS_EQUAL;
case rsx::comparaison_function::greater: return D3D12_COMPARISON_FUNC_GREATER;
case rsx::comparaison_function::not_equal: return D3D12_COMPARISON_FUNC_NOT_EQUAL;
case rsx::comparaison_function::greater_or_equal: return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
case rsx::comparaison_function::always: return D3D12_COMPARISON_FUNC_ALWAYS;
}
throw EXCEPTION("Invalid or unsupported compare func (0x%x)", op);
}
@ -371,24 +371,23 @@ DXGI_FORMAT get_depth_samplable_surface_format(rsx::surface_depth_format format)
throw EXCEPTION("Invalid format (0x%x)", format);
}
BOOL get_front_face_ccw(u32 ffv)
BOOL get_front_face_ccw(rsx::front_face ffv)
{
switch (ffv)
{
default: // Disgaea 3 pass some garbage value at startup, this is needed to survive.
case CELL_GCM_CW: return FALSE;
case CELL_GCM_CCW: return TRUE;
case rsx::front_face::cw: return FALSE;
case rsx::front_face::ccw: return TRUE;
}
throw EXCEPTION("Invalid front face value (0x%x)", ffv);
}
D3D12_CULL_MODE get_cull_face(u32 cfv)
D3D12_CULL_MODE get_cull_face(rsx::cull_face cfv)
{
switch (cfv)
{
case CELL_GCM_FRONT: return D3D12_CULL_MODE_FRONT;
case CELL_GCM_BACK: return D3D12_CULL_MODE_BACK;
default: return D3D12_CULL_MODE_NONE;
case rsx::cull_face::front: return D3D12_CULL_MODE_FRONT;
case rsx::cull_face::back: return D3D12_CULL_MODE_BACK;
case rsx::cull_face::front_and_back: return D3D12_CULL_MODE_NONE;
}
throw EXCEPTION("Invalid cull face value (0x%x)", cfv);
}
@ -489,13 +488,13 @@ DXGI_FORMAT get_vertex_attribute_format(rsx::vertex_base_type type, u8 size)
throw EXCEPTION("Invalid or unsupported type or size (type=0x%x, size=0x%x)", type, size);
}
D3D12_RECT get_scissor(u32 horizontal, u32 vertical)
D3D12_RECT get_scissor(u16 clip_origin_x, u16 clip_origin_y, u16 clip_w, u16 clip_h)
{
return{
horizontal & 0xFFFF,
vertical & 0xFFFF,
(horizontal & 0xFFFF) + (horizontal >> 16),
(vertical & 0xFFFF) + (vertical >> 16)
clip_origin_x,
clip_origin_y,
clip_w,
clip_h,
};
}
#endif

View File

@ -5,32 +5,32 @@
/**
* Convert GCM blend operator code to D3D12 one
*/
D3D12_BLEND_OP get_blend_op(u16 op);
D3D12_BLEND_OP get_blend_op(rsx::blend_equation op);
/**
* Convert GCM blend factor code to D3D12 one
*/
D3D12_BLEND get_blend_factor(u16 factor);
D3D12_BLEND get_blend_factor(rsx::blend_factor factor);
/**
* Convert GCM blend factor code to D3D12 one for alpha component
*/
D3D12_BLEND get_blend_factor_alpha(u16 factor);
D3D12_BLEND get_blend_factor_alpha(rsx::blend_factor factor);
/**
* Convert GCM logic op code to D3D12 one
*/
D3D12_LOGIC_OP get_logic_op(u32 op);
D3D12_LOGIC_OP get_logic_op(rsx::logic_op op);
/**
* Convert GCM stencil op code to D3D12 one
*/
D3D12_STENCIL_OP get_stencil_op(u32 op);
D3D12_STENCIL_OP get_stencil_op(rsx::stencil_op op);
/**
* Convert GCM comparison function code to D3D12 one.
*/
D3D12_COMPARISON_FUNC get_compare_func(u32 op);
D3D12_COMPARISON_FUNC get_compare_func(rsx::comparaison_function op);
/**
* Convert GCM texture format to an equivalent one supported by D3D12.
@ -91,12 +91,12 @@ DXGI_FORMAT get_depth_samplable_surface_format(rsx::surface_depth_format format)
/**
* Convert front face value to bool value telling wheter front face is counterclockwise or not
*/
BOOL get_front_face_ccw(u32 set_front_face_value);
BOOL get_front_face_ccw(rsx::front_face set_front_face_value);
/**
* Convert cull face value to a D3D12_CULL_MODE telling wheter cull face is front or back
*/
D3D12_CULL_MODE get_cull_face(u32 set_cull_face_value);
D3D12_CULL_MODE get_cull_face(rsx::cull_face set_cull_face_value);
/**
* Convert index type to DXGI_FORMAT
@ -111,4 +111,4 @@ DXGI_FORMAT get_vertex_attribute_format(rsx::vertex_base_type type, u8 size);
/**
* Convert scissor register value to D3D12_RECT
*/
D3D12_RECT get_scissor(u32 horizontal, u32 vertical);
D3D12_RECT get_scissor(u16 clip_origin_x, u16 clip_origin_y, u16 clip_w, u16 clip_h);

View File

@ -329,7 +329,7 @@ void D3D12GSRender::end()
m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();
get_current_resource_storage().command_list->SetGraphicsRootSignature(m_shared_root_signature.Get());
get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]);
get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers.stencil_func_ref());
std::chrono::time_point<std::chrono::system_clock> constants_duration_start = std::chrono::system_clock::now();
@ -425,8 +425,8 @@ void D3D12GSRender::end()
m_timers.texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count();
set_rtt_and_ds(get_current_resource_storage().command_list.Get());
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
D3D12_VIEWPORT viewport =
{
@ -434,12 +434,13 @@ void D3D12GSRender::end()
0.f,
(float)clip_w,
(float)clip_h,
(f32&)rsx::method_registers[NV4097_SET_CLIP_MIN],
(f32&)rsx::method_registers[NV4097_SET_CLIP_MAX]
rsx::method_registers.clip_min(),
rsx::method_registers.clip_max(),
};
get_current_resource_storage().command_list->RSSetViewports(1, &viewport);
get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(),
rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(draw_mode));
@ -485,7 +486,7 @@ void D3D12GSRender::flip(int buffer)
ID3D12Resource *resource_to_flip;
float viewport_w, viewport_h;
if (!is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
if (!is_flip_surface_in_global_memory(rsx::method_registers.surface_color_target()))
{
resource_storage &storage = get_current_resource_storage();
VERIFY(storage.ram_framebuffer == nullptr);
@ -577,7 +578,7 @@ void D3D12GSRender::flip(int buffer)
shader_resource_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shader_resource_view_desc.Texture2D.MipLevels = 1;
if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
if (is_flip_surface_in_global_memory(rsx::method_registers.surface_color_target()))
shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
else
shader_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
@ -622,7 +623,7 @@ void D3D12GSRender::flip(int buffer)
if (!g_cfg_rsx_overlay)
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) && resource_to_flip != nullptr)
if (is_flip_surface_in_global_memory(rsx::method_registers.surface_color_target()) && resource_to_flip != nullptr)
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(resource_to_flip, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());

View File

@ -61,8 +61,6 @@ private:
data_cache m_texture_cache;
bool invalidate_address(u32 addr);
rsx::surface_info m_surface;
RSXVertexProgram m_vertex_program;
RSXFragmentProgram m_fragment_program;
PipelineStateObjectCache m_pso_cache;

View File

@ -60,72 +60,72 @@ void D3D12GSRender::load_program()
};
prop.Blend = CD3D12_BLEND_DESC;
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE])
if (rsx::method_registers.blend_enabled())
{
prop.Blend.RenderTarget[0].BlendEnable = true;
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x2)
if (rsx::method_registers.blend_enabled_surface_1())
prop.Blend.RenderTarget[1].BlendEnable = true;
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x4)
if (rsx::method_registers.blend_enabled_surface_2())
prop.Blend.RenderTarget[2].BlendEnable = true;
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x8)
if (rsx::method_registers.blend_enabled_surface_3())
prop.Blend.RenderTarget[3].BlendEnable = true;
prop.Blend.RenderTarget[0].BlendOp = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] & 0xFFFF);
prop.Blend.RenderTarget[0].BlendOpAlpha = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] >> 16);
prop.Blend.RenderTarget[0].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
prop.Blend.RenderTarget[0].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x2)
if (rsx::method_registers.blend_enabled_surface_1())
{
prop.Blend.RenderTarget[1].BlendOp = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] & 0xFFFF);
prop.Blend.RenderTarget[1].BlendOpAlpha = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] >> 16);
prop.Blend.RenderTarget[1].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
prop.Blend.RenderTarget[1].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
}
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x4)
if (rsx::method_registers.blend_enabled_surface_2())
{
prop.Blend.RenderTarget[2].BlendOp = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] & 0xFFFF);
prop.Blend.RenderTarget[2].BlendOpAlpha = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] >> 16);
prop.Blend.RenderTarget[2].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
prop.Blend.RenderTarget[2].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
}
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x8)
if (rsx::method_registers.blend_enabled_surface_3())
{
prop.Blend.RenderTarget[3].BlendOp = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] & 0xFFFF);
prop.Blend.RenderTarget[3].BlendOpAlpha = get_blend_op(rsx::method_registers[NV4097_SET_BLEND_EQUATION] >> 16);
prop.Blend.RenderTarget[3].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
prop.Blend.RenderTarget[3].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
}
prop.Blend.RenderTarget[0].SrcBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[0].DestBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[0].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] >> 16);
prop.Blend.RenderTarget[0].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] >> 16);
prop.Blend.RenderTarget[0].SrcBlend = get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb());
prop.Blend.RenderTarget[0].DestBlend = get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb());
prop.Blend.RenderTarget[0].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_sfactor_a());
prop.Blend.RenderTarget[0].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_dfactor_a());
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x2)
if (rsx::method_registers.blend_enabled_surface_1())
{
prop.Blend.RenderTarget[1].SrcBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[1].DestBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[1].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] >> 16);
prop.Blend.RenderTarget[1].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] >> 16);
prop.Blend.RenderTarget[1].SrcBlend = get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb());
prop.Blend.RenderTarget[1].DestBlend = get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb());
prop.Blend.RenderTarget[1].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_sfactor_a());
prop.Blend.RenderTarget[1].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_dfactor_a());
}
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x4)
if (rsx::method_registers.blend_enabled_surface_2())
{
prop.Blend.RenderTarget[2].SrcBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[2].DestBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[2].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] >> 16);
prop.Blend.RenderTarget[2].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] >> 16);
prop.Blend.RenderTarget[2].SrcBlend = get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb());
prop.Blend.RenderTarget[2].DestBlend = get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb());
prop.Blend.RenderTarget[2].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_sfactor_a());
prop.Blend.RenderTarget[2].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_dfactor_a());
}
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT] & 0x8)
if (rsx::method_registers.blend_enabled_surface_3())
{
prop.Blend.RenderTarget[3].SrcBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[3].DestBlend = get_blend_factor(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] & 0xFFFF);
prop.Blend.RenderTarget[3].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] >> 16);
prop.Blend.RenderTarget[3].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] >> 16);
prop.Blend.RenderTarget[3].SrcBlend = get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb());
prop.Blend.RenderTarget[3].DestBlend = get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb());
prop.Blend.RenderTarget[3].SrcBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_sfactor_a());
prop.Blend.RenderTarget[3].DestBlendAlpha = get_blend_factor_alpha(rsx::method_registers.blend_func_dfactor_a());
}
}
if (rsx::method_registers[NV4097_SET_LOGIC_OP_ENABLE])
if (rsx::method_registers.logic_op_enabled())
{
prop.Blend.RenderTarget[0].LogicOpEnable = true;
prop.Blend.RenderTarget[0].LogicOp = get_logic_op(rsx::method_registers[NV4097_SET_LOGIC_OP]);
prop.Blend.RenderTarget[0].LogicOp = get_logic_op(rsx::method_registers.logic_operation());
}
// if (m_set_blend_color)
@ -133,10 +133,10 @@ void D3D12GSRender::load_program()
// glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a);
// checkForGlError("glBlendColor");
}
prop.DepthStencilFormat = get_depth_stencil_surface_format(m_surface.depth_format);
prop.RenderTargetsFormat = get_color_surface_format(m_surface.color_format);
prop.DepthStencilFormat = get_depth_stencil_surface_format(rsx::method_registers.surface_depth_fmt());
prop.RenderTargetsFormat = get_color_surface_format(rsx::method_registers.surface_color());
switch (rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
switch (rsx::method_registers.surface_color_target())
{
case rsx::surface_target::surface_a:
case rsx::surface_target::surface_b:
@ -154,36 +154,36 @@ void D3D12GSRender::load_program()
default:
break;
}
if (!!(rsx::method_registers[NV4097_SET_DEPTH_TEST_ENABLE]))
if (rsx::method_registers.depth_test_enabled())
{
prop.DepthStencil.DepthEnable = TRUE;
prop.DepthStencil.DepthFunc = get_compare_func(rsx::method_registers[NV4097_SET_DEPTH_FUNC]);
prop.DepthStencil.DepthFunc = get_compare_func(rsx::method_registers.depth_func());
}
else
prop.DepthStencil.DepthEnable = FALSE;
prop.DepthStencil.DepthWriteMask = !!(rsx::method_registers[NV4097_SET_DEPTH_MASK]) ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
prop.DepthStencil.StencilEnable = !!(rsx::method_registers[NV4097_SET_STENCIL_TEST_ENABLE]);
prop.DepthStencil.StencilReadMask = rsx::method_registers[NV4097_SET_STENCIL_FUNC_MASK];
prop.DepthStencil.StencilWriteMask = rsx::method_registers[NV4097_SET_STENCIL_MASK];
prop.DepthStencil.FrontFace.StencilPassOp = get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]);
prop.DepthStencil.FrontFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL]);
prop.DepthStencil.FrontFace.StencilFailOp = get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL]);
prop.DepthStencil.FrontFace.StencilFunc = get_compare_func(rsx::method_registers[NV4097_SET_STENCIL_FUNC]);
prop.DepthStencil.DepthWriteMask = rsx::method_registers.depth_write_enabled() ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
prop.DepthStencil.StencilEnable = rsx::method_registers.stencil_test_enabled();
prop.DepthStencil.StencilReadMask = rsx::method_registers.stencil_func_mask();
prop.DepthStencil.StencilWriteMask = rsx::method_registers.stencil_mask();
prop.DepthStencil.FrontFace.StencilPassOp = get_stencil_op(rsx::method_registers.stencil_op_zpass());
prop.DepthStencil.FrontFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers.stencil_op_zfail());
prop.DepthStencil.FrontFace.StencilFailOp = get_stencil_op(rsx::method_registers.stencil_op_fail());
prop.DepthStencil.FrontFace.StencilFunc = get_compare_func(rsx::method_registers.stencil_func());
if (rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE])
if (rsx::method_registers.two_sided_stencil_test_enabled())
{
prop.DepthStencil.BackFace.StencilFailOp = get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL]);
prop.DepthStencil.BackFace.StencilFunc = get_compare_func(rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC]);
prop.DepthStencil.BackFace.StencilPassOp = get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS]);
prop.DepthStencil.BackFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL]);
prop.DepthStencil.BackFace.StencilFailOp = get_stencil_op(rsx::method_registers.back_stencil_op_fail());
prop.DepthStencil.BackFace.StencilFunc = get_compare_func(rsx::method_registers.back_stencil_func());
prop.DepthStencil.BackFace.StencilPassOp = get_stencil_op(rsx::method_registers.back_stencil_op_zpass());
prop.DepthStencil.BackFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers.back_stencil_op_zfail());
}
else
{
prop.DepthStencil.BackFace.StencilPassOp = get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]);
prop.DepthStencil.BackFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL]);
prop.DepthStencil.BackFace.StencilFailOp = get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL]);
prop.DepthStencil.BackFace.StencilFunc = get_compare_func(rsx::method_registers[NV4097_SET_STENCIL_FUNC]);
prop.DepthStencil.BackFace.StencilPassOp = get_stencil_op(rsx::method_registers.stencil_op_zpass());
prop.DepthStencil.BackFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers.stencil_op_zfail());
prop.DepthStencil.BackFace.StencilFailOp = get_stencil_op(rsx::method_registers.stencil_op_fail());
prop.DepthStencil.BackFace.StencilFunc = get_compare_func(rsx::method_registers.stencil_func());
}
// Sensible default value
@ -202,25 +202,25 @@ void D3D12GSRender::load_program()
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
};
prop.Rasterization = CD3D12_RASTERIZER_DESC;
if (!!rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE])
if (rsx::method_registers.cull_face_enabled())
{
prop.Rasterization.CullMode = get_cull_face(rsx::method_registers[NV4097_SET_CULL_FACE]);
prop.Rasterization.CullMode = get_cull_face(rsx::method_registers.cull_face_mode());
}
prop.Rasterization.FrontCounterClockwise = get_front_face_ccw(rsx::method_registers[NV4097_SET_FRONT_FACE]);
prop.Rasterization.FrontCounterClockwise = get_front_face_ccw(rsx::method_registers.front_face_mode());
UINT8 mask = 0;
mask |= (rsx::method_registers[NV4097_SET_COLOR_MASK] >> 16) & 0xFF ? D3D12_COLOR_WRITE_ENABLE_RED : 0;
mask |= (rsx::method_registers[NV4097_SET_COLOR_MASK] >> 8) & 0xFF ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0;
mask |= rsx::method_registers[NV4097_SET_COLOR_MASK] & 0xFF ? D3D12_COLOR_WRITE_ENABLE_BLUE : 0;
mask |= (rsx::method_registers[NV4097_SET_COLOR_MASK] >> 24) & 0xFF ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0;
mask |= rsx::method_registers.color_mask_r() ? D3D12_COLOR_WRITE_ENABLE_RED : 0;
mask |= rsx::method_registers.color_mask_g() ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0;
mask |= rsx::method_registers.color_mask_b() ? D3D12_COLOR_WRITE_ENABLE_BLUE : 0;
mask |= rsx::method_registers.color_mask_a() ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0;
for (unsigned i = 0; i < prop.numMRT; i++)
prop.Blend.RenderTarget[i].RenderTargetWriteMask = mask;
if (!!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE])
if (rsx::method_registers.restart_index_enabled())
{
rsx::index_array_type index_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
rsx::index_array_type index_type = rsx::method_registers.index_type();
if (index_type == rsx::index_array_type::u32)
{
prop.CutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;

View File

@ -56,21 +56,6 @@ namespace
throw EXCEPTION("Wrong color_target (%d)", color_target);
}
std::array<float, 4> get_clear_color(u32 clear_color)
{
u8 clear_a = clear_color >> 24;
u8 clear_r = clear_color >> 16;
u8 clear_g = clear_color >> 8;
u8 clear_b = clear_color;
return
{
clear_r / 255.0f,
clear_g / 255.0f,
clear_b / 255.0f,
clear_a / 255.0f
};
}
u8 get_clear_stencil(u32 register_value)
{
return register_value & 0xff;
@ -123,8 +108,6 @@ namespace
void D3D12GSRender::clear_surface(u32 arg)
{
if (!rsx::method_registers[NV4097_SET_SURFACE_FORMAT]) return;
std::chrono::time_point<std::chrono::system_clock> start_duration = std::chrono::system_clock::now();
std::chrono::time_point<std::chrono::system_clock> rtt_duration_start = std::chrono::system_clock::now();
@ -139,25 +122,32 @@ void D3D12GSRender::clear_surface(u32 arg)
if (arg & 0x1)
{
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
u32 max_depth_value = get_max_depth_value(m_surface.depth_format);
u32 clear_depth = rsx::method_registers.z_clear_value();
u32 max_depth_value = get_max_depth_value(rsx::method_registers.surface_depth_fmt());
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
}
if (arg & 0x2)
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]),
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers.stencil_clear_value()),
1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
}
if (arg & 0xF0)
{
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle);
size_t rtt_index = get_num_rtt(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]));
size_t rtt_index = get_num_rtt(rsx::method_registers.surface_color_target());
get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
std::array<float, 4> clear_color =
{
rsx::method_registers.clear_color_r() / 255.f,
rsx::method_registers.clear_color_g() / 255.f,
rsx::method_registers.clear_color_b() / 255.f,
rsx::method_registers.clear_color_a() / 255.f,
};
for (unsigned i = 0; i < rtt_index; i++)
get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, m_descriptor_stride_rtv), get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]).data(),
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, m_descriptor_stride_rtv), clear_color.data(),
1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
}
std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now();
@ -174,28 +164,27 @@ void D3D12GSRender::clear_surface(u32 arg)
void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist)
{
// check if something has changed
u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT];
// Exit early if there is no rtt changes
if (!m_rtts_dirty)
return;
m_rtts_dirty = false;
if (m_surface.format != surface_format)
m_surface.unpack(surface_format);
std::array<float, 4> clear_color = get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]);
std::array<float, 4> clear_color =
{
rsx::method_registers.clear_color_r() / 255.f,
rsx::method_registers.clear_color_g() / 255.f,
rsx::method_registers.clear_color_b() / 255.f,
rsx::method_registers.clear_color_a() / 255.f,
};
m_rtts.prepare_render_target(copycmdlist,
rsx::method_registers[NV4097_SET_SURFACE_FORMAT],
rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL], rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL],
rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]),
rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(),
rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height(),
rsx::method_registers.surface_color_target(),
get_color_surface_addresses(), get_zeta_surface_address(),
m_device.Get(), clear_color, 1.f, 0);
// write descriptors
DXGI_FORMAT dxgi_format = get_color_surface_format(m_surface.color_format);
DXGI_FORMAT dxgi_format = get_color_surface_format(rsx::method_registers.surface_color());
D3D12_RENDER_TARGET_VIEW_DESC rtt_view_desc = {};
rtt_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtt_view_desc.Format = dxgi_format;
@ -203,7 +192,7 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
m_rtts.current_rtts_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * m_descriptor_stride_rtv);
size_t rtt_index = 0;
for (u8 i : get_rtt_indexes(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
{
if (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
continue;
@ -219,14 +208,14 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * m_descriptor_stride_dsv);
get_current_resource_storage().depth_stencil_descriptor_heap_index += 1;
D3D12_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {};
depth_stencil_view_desc.Format = get_depth_stencil_surface_format(m_surface.depth_format);
depth_stencil_view_desc.Format = get_depth_stencil_surface_format(rsx::method_registers.surface_depth_fmt());
depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
m_device->CreateDepthStencilView(std::get<1>(m_rtts.m_bound_depth_stencil), &depth_stencil_view_desc, m_rtts.current_ds_handle);
}
void D3D12GSRender::set_rtt_and_ds(ID3D12GraphicsCommandList *command_list)
{
UINT num_rtt = get_num_rtt(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]));
UINT num_rtt = get_num_rtt(rsx::method_registers.surface_color_target());
D3D12_CPU_DESCRIPTOR_HANDLE* ds_handle = (std::get<1>(m_rtts.m_bound_depth_stencil) != nullptr) ? &m_rtts.current_ds_handle : nullptr;
command_list->OMSetRenderTargets((UINT)num_rtt, &m_rtts.current_rtts_handle, true, ds_handle);
}
@ -250,8 +239,8 @@ namespace
rsx::surface_color_format color_surface_format
)
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
DXGI_FORMAT dxgi_format = get_color_surface_format(color_surface_format);
size_t row_pitch = get_aligned_pitch(color_surface_format, clip_w);
@ -300,42 +289,25 @@ void D3D12GSRender::copy_render_target_to_dma_location()
// Add all buffer write
// Cell can't make any assumption about readyness of color/depth buffer
// Except when a semaphore is written by RSX
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
size_t depth_row_pitch = align(clip_w * 4, 256);
size_t depth_buffer_offset_in_heap = 0;
u32 context_dma_color[] =
{
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D],
};
u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
u32 offset_color[] =
{
rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET]
};
u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET];
u32 address_color[] =
{
rsx::get_address(offset_color[0], context_dma_color[0]),
rsx::get_address(offset_color[1], context_dma_color[1]),
rsx::get_address(offset_color[2], context_dma_color[2]),
rsx::get_address(offset_color[3], context_dma_color[3]),
rsx::get_address(rsx::method_registers.surface_a_offset(), rsx::method_registers.surface_a_dma()),
rsx::get_address(rsx::method_registers.surface_b_offset(), rsx::method_registers.surface_b_dma()),
rsx::get_address(rsx::method_registers.surface_c_offset(), rsx::method_registers.surface_c_dma()),
rsx::get_address(rsx::method_registers.surface_d_offset(), rsx::method_registers.surface_d_dma()),
};
u32 address_z = rsx::get_address(offset_zeta, m_context_dma_z);
u32 address_z = rsx::get_address(rsx::method_registers.surface_z_offset(), rsx::method_registers.surface_z_dma());
bool need_transfer = false;
if (m_context_dma_z && g_cfg_rsx_write_depth_buffer)
if (rsx::method_registers.surface_z_dma() && g_cfg_rsx_write_depth_buffer)
{
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { depth_buffer_offset_in_heap,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0,
@ -349,11 +321,11 @@ void D3D12GSRender::copy_render_target_to_dma_location()
size_t color_buffer_offset_in_heap[4];
if (g_cfg_rsx_write_color_buffers)
{
for (u8 i : get_rtt_indexes(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
{
if (!address_color[i])
continue;
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[i]), m_surface.color_format);
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[i]), rsx::method_registers.surface_color());
invalidate_address(address_color[i]);
need_transfer = true;
}
@ -390,8 +362,8 @@ void D3D12GSRender::copy_render_target_to_dma_location()
if (g_cfg_rsx_write_color_buffers)
{
size_t srcPitch = get_aligned_pitch(m_surface.color_format, clip_w);
size_t dstPitch = get_packed_pitch(m_surface.color_format, clip_w);
size_t srcPitch = get_aligned_pitch(rsx::method_registers.surface_color(), clip_w);
size_t dstPitch = get_packed_pitch(rsx::method_registers.surface_color(), clip_w);
void *dest_buffer[] =
{
@ -401,7 +373,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
vm::base(address_color[3]),
};
for (u8 i : get_rtt_indexes(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
{
if (!address_color[i])
continue;
@ -413,19 +385,15 @@ void D3D12GSRender::copy_render_target_to_dma_location()
std::array<std::vector<gsl::byte>, 4> D3D12GSRender::copy_render_targets_to_memory()
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
return m_rtts.get_render_targets_data(surface.color_format, clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
return m_rtts.get_render_targets_data(rsx::method_registers.surface_color(), clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
}
std::array<std::vector<gsl::byte>, 2> D3D12GSRender::copy_depth_stencil_buffer_to_memory()
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
return m_rtts.get_depth_stencil_data(surface.depth_format, clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
return m_rtts.get_depth_stencil_data(rsx::method_registers.surface_depth_fmt(), clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
}
#endif

View File

@ -6,6 +6,7 @@
#include "../Common/TextureUtils.h"
// For clarity this code deals with texture but belongs to D3D12GSRender class
#include "D3D12Formats.h"
#include "../rsx_methods.h"
namespace
{
@ -174,7 +175,7 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
continue;
m_textures_dirty[i] = false;
if (!textures[i].enabled())
if (!rsx::method_registers.fragment_textures[i].enabled())
{
// Now fill remaining texture slots with dummy texture/sampler
@ -205,13 +206,13 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
continue;
}
size_t w = textures[i].width(), h = textures[i].height();
size_t w = rsx::method_registers.fragment_textures[i].width(), h = rsx::method_registers.fragment_textures[i].height();
// if (!w || !h) continue;
const u32 texaddr = rsx::get_address(textures[i].offset(), textures[i].location());
const u32 texaddr = rsx::get_address(rsx::method_registers.fragment_textures[i].offset(), rsx::method_registers.fragment_textures[i].location());
const u8 format = textures[i].format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
bool is_swizzled = !(textures[i].format() & CELL_GCM_TEXTURE_LN);
const u8 format = rsx::method_registers.fragment_textures[i].format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
bool is_swizzled = !(rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_LN);
ID3D12Resource *vram_texture;
std::pair<texture_entry, ComPtr<ID3D12Resource> > *cached_texture = m_texture_cache.find_data_if_available(texaddr);
@ -225,13 +226,13 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
{
is_depth_stencil_texture = true;
}
else if (cached_texture != nullptr && (cached_texture->first == texture_entry(format, w, h, textures[i].depth(), textures[i].get_exact_mipmap_count())))
else if (cached_texture != nullptr && (cached_texture->first == texture_entry(format, w, h, rsx::method_registers.fragment_textures[i].depth(), rsx::method_registers.fragment_textures[i].get_exact_mipmap_count())))
{
if (cached_texture->first.m_is_dirty)
{
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(cached_texture->second.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST));
update_existing_texture(textures[i], command_list, m_buffer_data, cached_texture->second.Get());
m_texture_cache.protect_data(texaddr, texaddr, get_texture_size(textures[i]));
update_existing_texture(rsx::method_registers.fragment_textures[i], command_list, m_buffer_data, cached_texture->second.Get());
m_texture_cache.protect_data(texaddr, texaddr, get_texture_size(rsx::method_registers.fragment_textures[i]));
}
vram_texture = cached_texture->second.Get();
}
@ -239,14 +240,14 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
{
if (cached_texture != nullptr)
get_current_resource_storage().dirty_textures.push_back(m_texture_cache.remove_from_cache(texaddr));
ComPtr<ID3D12Resource> tex = upload_single_texture(textures[i], m_device.Get(), command_list, m_buffer_data);
ComPtr<ID3D12Resource> tex = upload_single_texture(rsx::method_registers.fragment_textures[i], m_device.Get(), command_list, m_buffer_data);
std::wstring name = L"texture_@" + std::to_wstring(texaddr);
tex->SetName(name.c_str());
vram_texture = tex.Get();
m_texture_cache.store_and_protect_data(texaddr, texaddr, get_texture_size(textures[i]), format, w, h, textures[i].depth(), textures[i].get_exact_mipmap_count(), tex);
m_texture_cache.store_and_protect_data(texaddr, texaddr, get_texture_size(rsx::method_registers.fragment_textures[i]), format, w, h, rsx::method_registers.fragment_textures[i].depth(), rsx::method_registers.fragment_textures[i].get_exact_mipmap_count(), tex);
}
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = get_srv_descriptor_with_dimensions(textures[i]);
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = get_srv_descriptor_with_dimensions(rsx::method_registers.fragment_textures[i]);
shared_resource_view_desc.Format = get_texture_format(format);
switch (format)
@ -339,10 +340,10 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
{
u8 remap_a = textures[i].remap() & 0x3;
u8 remap_r = (textures[i].remap() >> 2) & 0x3;
u8 remap_g = (textures[i].remap() >> 4) & 0x3;
u8 remap_b = (textures[i].remap() >> 6) & 0x3;
u8 remap_a = rsx::method_registers.fragment_textures[i].remap() & 0x3;
u8 remap_r = (rsx::method_registers.fragment_textures[i].remap() >> 2) & 0x3;
u8 remap_g = (rsx::method_registers.fragment_textures[i].remap() >> 4) & 0x3;
u8 remap_b = (rsx::method_registers.fragment_textures[i].remap() >> 6) & 0x3;
if (is_render_target)
{
@ -399,7 +400,7 @@ void D3D12GSRender::upload_textures(ID3D12GraphicsCommandList *command_list, siz
.Offset((UINT)i, m_descriptor_stride_srv_cbv_uav)
);
m_device->CreateSampler(&get_sampler_desc(textures[i]),
m_device->CreateSampler(&get_sampler_desc(rsx::method_registers.fragment_textures[i]),
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_sampler_descriptors->GetCPUDescriptorHandleForHeapStart())
.Offset((UINT)i, m_descriptor_stride_samplers));
}

View File

@ -1036,6 +1036,260 @@ rsx::surface_color_format rsx::to_surface_color_format(u8 in)
throw EXCEPTION("unknow surface color format %x", in);
}
rsx::stencil_op rsx::to_stencil_op(u16 in)
{
switch (in)
{
case CELL_GCM_KEEP: return rsx::stencil_op::keep;
case CELL_GCM_REPLACE: return rsx::stencil_op::replace;
case CELL_GCM_INCR: return rsx::stencil_op::incr;
case CELL_GCM_DECR: return rsx::stencil_op::decr;
case CELL_GCM_INCR_WRAP: return rsx::stencil_op::incr_wrap;
case CELL_GCM_DECR_WRAP: return rsx::stencil_op::decr_wrap;
case CELL_GCM_ZERO: return rsx::stencil_op::zero;
}
throw EXCEPTION("unknow stencil op %x", in);
}
rsx::blend_equation rsx::to_blend_equation(u16 in)
{
switch (in)
{
case CELL_GCM_FUNC_ADD: return rsx::blend_equation::add;
case CELL_GCM_MIN: return rsx::blend_equation::min;
case CELL_GCM_MAX: return rsx::blend_equation::max;
case CELL_GCM_FUNC_SUBTRACT: return rsx::blend_equation::substract;
case CELL_GCM_FUNC_REVERSE_SUBTRACT: return rsx::blend_equation::reverse_substract;
case CELL_GCM_FUNC_REVERSE_SUBTRACT_SIGNED: return rsx::blend_equation::reverse_substract_signed;
case CELL_GCM_FUNC_ADD_SIGNED: return rsx::blend_equation::add_signed;
case CELL_GCM_FUNC_REVERSE_ADD_SIGNED: return rsx::blend_equation::reverse_add_signed;
}
throw EXCEPTION("unknow blend eq %x", in);
}
rsx::blend_factor rsx::to_blend_factor(u16 in)
{
switch (in)
{
case CELL_GCM_ZERO: return rsx::blend_factor::zero;
case CELL_GCM_ONE: return rsx::blend_factor::one;
case CELL_GCM_SRC_COLOR: return rsx::blend_factor::src_color;
case CELL_GCM_ONE_MINUS_SRC_COLOR: return rsx::blend_factor::one_minus_src_color;
case CELL_GCM_SRC_ALPHA: return rsx::blend_factor::src_alpha;
case CELL_GCM_ONE_MINUS_SRC_ALPHA: return rsx::blend_factor::one_minus_src_alpha;
case CELL_GCM_DST_ALPHA: return rsx::blend_factor::dst_alpha;
case CELL_GCM_ONE_MINUS_DST_ALPHA: return rsx::blend_factor::one_minus_dst_alpha;
case CELL_GCM_DST_COLOR: return rsx::blend_factor::dst_color;
case CELL_GCM_ONE_MINUS_DST_COLOR: return rsx::blend_factor::one_minus_dst_color;
case CELL_GCM_SRC_ALPHA_SATURATE: return rsx::blend_factor::src_alpha_saturate;
case CELL_GCM_CONSTANT_COLOR: return rsx::blend_factor::constant_color;
case CELL_GCM_ONE_MINUS_CONSTANT_COLOR: return rsx::blend_factor::one_minus_constant_color;
case CELL_GCM_CONSTANT_ALPHA: return rsx::blend_factor::constant_alpha;
case CELL_GCM_ONE_MINUS_CONSTANT_ALPHA: return rsx::blend_factor::one_minus_constant_alpha;
}
throw EXCEPTION("unknow blend factor %x", in);
}
rsx::logic_op rsx::to_logic_op(u16 in)
{
switch (in)
{
case CELL_GCM_CLEAR: return rsx::logic_op::logic_clear;
case CELL_GCM_AND: return rsx::logic_op::logic_and;
case CELL_GCM_AND_REVERSE: return rsx::logic_op::logic_and_reverse;
case CELL_GCM_COPY: return rsx::logic_op::logic_copy;
case CELL_GCM_AND_INVERTED: return rsx::logic_op::logic_and_inverted;
case CELL_GCM_NOOP: return rsx::logic_op::logic_noop;
case CELL_GCM_XOR: return rsx::logic_op::logic_xor;
case CELL_GCM_OR: return rsx::logic_op::logic_or;
case CELL_GCM_NOR: return rsx::logic_op::logic_nor;
case CELL_GCM_EQUIV: return rsx::logic_op::logic_equiv;
case CELL_GCM_INVERT: return rsx::logic_op::logic_invert;
case CELL_GCM_OR_REVERSE: return rsx::logic_op::logic_or_reverse;
case CELL_GCM_COPY_INVERTED: return rsx::logic_op::logic_copy_inverted;
case CELL_GCM_OR_INVERTED: return rsx::logic_op::logic_or_inverted;
case CELL_GCM_NAND: return rsx::logic_op::logic_nand;
case CELL_GCM_SET: return rsx::logic_op::logic_set;
}
throw EXCEPTION("unknow logic op %x", in);
}
rsx::front_face rsx::to_front_face(u16 in)
{
switch (in)
{
case CELL_GCM_CW: return rsx::front_face::cw;
case CELL_GCM_CCW: return rsx::front_face::ccw;
}
throw EXCEPTION("unknow front face %x", in);
}
rsx::cull_face rsx::to_cull_face(u16 in)
{
switch (in)
{
case CELL_GCM_FRONT_AND_BACK: return rsx::cull_face::front_and_back;
case CELL_GCM_FRONT: return rsx::cull_face::front;
case CELL_GCM_BACK: return rsx::cull_face::back;
}
throw EXCEPTION("unknow cull face %x", in);
}
enum
{
CELL_GCM_TRANSFER_ORIGIN_CENTER = 1,
CELL_GCM_TRANSFER_ORIGIN_CORNER = 2,
CELL_GCM_TRANSFER_INTERPOLATOR_ZOH = 0,
CELL_GCM_TRANSFER_INTERPOLATOR_FOH = 1,
};
rsx::blit_engine::transfer_origin rsx::blit_engine::to_transfer_origin(u8 in)
{
switch (in)
{
case CELL_GCM_TRANSFER_ORIGIN_CENTER: return rsx::blit_engine::transfer_origin::center;
case CELL_GCM_TRANSFER_ORIGIN_CORNER: return rsx::blit_engine::transfer_origin::corner;
}
throw EXCEPTION("unknow tranfer origin %x", in);
}
rsx::blit_engine::transfer_interpolator rsx::blit_engine::to_transfer_interpolator(u8 in)
{
switch (in)
{
case CELL_GCM_TRANSFER_INTERPOLATOR_ZOH: return rsx::blit_engine::transfer_interpolator::zoh;
case CELL_GCM_TRANSFER_INTERPOLATOR_FOH: return rsx::blit_engine::transfer_interpolator::foh;
}
throw EXCEPTION("unknow tranfer interpolator %x", in);
}
enum
{
CELL_GCM_TRANSFER_OPERATION_SRCCOPY_AND = 0,
CELL_GCM_TRANSFER_OPERATION_ROP_AND = 1,
CELL_GCM_TRANSFER_OPERATION_BLEND_AND = 2,
CELL_GCM_TRANSFER_OPERATION_SRCCOPY = 3,
CELL_GCM_TRANSFER_OPERATION_SRCCOPY_PREMULT = 4,
CELL_GCM_TRANSFER_OPERATION_BLEND_PREMULT = 5,
};
rsx::blit_engine::transfer_operation rsx::blit_engine::to_transfer_operation(u8 in)
{
switch (in)
{
case CELL_GCM_TRANSFER_OPERATION_SRCCOPY_AND: return rsx::blit_engine::transfer_operation::srccopy_and;
case CELL_GCM_TRANSFER_OPERATION_ROP_AND: return rsx::blit_engine::transfer_operation::rop_and;
case CELL_GCM_TRANSFER_OPERATION_BLEND_AND: return rsx::blit_engine::transfer_operation::blend_and;
case CELL_GCM_TRANSFER_OPERATION_SRCCOPY: return rsx::blit_engine::transfer_operation::srccopy;
case CELL_GCM_TRANSFER_OPERATION_SRCCOPY_PREMULT: return rsx::blit_engine::transfer_operation::srccopy_premult;
case CELL_GCM_TRANSFER_OPERATION_BLEND_PREMULT: return rsx::blit_engine::transfer_operation::blend_premult;
}
throw EXCEPTION("unknow tranfer operation %x", in);
}
enum
{
CELL_GCM_TRANSFER_SCALE_FORMAT_A1R5G5B5 = 1,
CELL_GCM_TRANSFER_SCALE_FORMAT_X1R5G5B5 = 2,
CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8 = 3,
CELL_GCM_TRANSFER_SCALE_FORMAT_X8R8G8B8 = 4,
CELL_GCM_TRANSFER_SCALE_FORMAT_CR8YB8CB8YA8 = 5,
CELL_GCM_TRANSFER_SCALE_FORMAT_YB8CR8YA8CB8 = 6,
CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 = 7,
CELL_GCM_TRANSFER_SCALE_FORMAT_Y8 = 8,
CELL_GCM_TRANSFER_SCALE_FORMAT_AY8 = 9,
CELL_GCM_TRANSFER_SCALE_FORMAT_EYB8ECR8EYA8ECB8 = 10,
CELL_GCM_TRANSFER_SCALE_FORMAT_ECR8EYB8ECB8EYA8 = 11,
CELL_GCM_TRANSFER_SCALE_FORMAT_A8B8G8R8 = 12,
CELL_GCM_TRANSFER_SCALE_FORMAT_X8B8G8R8 = 13,
};
rsx::blit_engine::transfer_source_format rsx::blit_engine::to_transfer_source_format(u8 in)
{
switch (in)
{
case CELL_GCM_TRANSFER_SCALE_FORMAT_A1R5G5B5: return rsx::blit_engine::transfer_source_format::a1r5g5b5;
case CELL_GCM_TRANSFER_SCALE_FORMAT_X1R5G5B5: return rsx::blit_engine::transfer_source_format::x1r5g5b5;
case CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8: return rsx::blit_engine::transfer_source_format::a8r8g8b8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_X8R8G8B8: return rsx::blit_engine::transfer_source_format::x8r8g8b8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_CR8YB8CB8YA8: return rsx::blit_engine::transfer_source_format::cr8yb8cb8ya8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_YB8CR8YA8CB8: return rsx::blit_engine::transfer_source_format::yb8cr8ya8cb8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5: return rsx::blit_engine::transfer_source_format::r5g6b5;
case CELL_GCM_TRANSFER_SCALE_FORMAT_Y8: return rsx::blit_engine::transfer_source_format::y8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_AY8: return rsx::blit_engine::transfer_source_format::ay8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_EYB8ECR8EYA8ECB8: return rsx::blit_engine::transfer_source_format::eyb8ecr8eya8ecb8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_ECR8EYB8ECB8EYA8: return rsx::blit_engine::transfer_source_format::ecr8eyb8ecb8eya8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_A8B8G8R8: return rsx::blit_engine::transfer_source_format::a8b8g8r8;
case CELL_GCM_TRANSFER_SCALE_FORMAT_X8B8G8R8: return rsx::blit_engine::transfer_source_format::x8b8g8r8;
}
throw EXCEPTION("unknow transfer source format %x", in);
}
enum
{
// Destination Format conversions
CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 = 4,
CELL_GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8 = 10,
CELL_GCM_TRANSFER_SURFACE_FORMAT_Y32 = 11,
};
rsx::blit_engine::transfer_destination_format rsx::blit_engine::to_transfer_destination_format(u8 in)
{
switch (in)
{
case CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5: return rsx::blit_engine::transfer_destination_format::r5g6b5;
case CELL_GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8: return rsx::blit_engine::transfer_destination_format::a8r8g8b8;
case CELL_GCM_TRANSFER_SURFACE_FORMAT_Y32: return rsx::blit_engine::transfer_destination_format::y32;
}
throw EXCEPTION("unknow transfer destination format %x", in);
}
enum
{
CELL_GCM_CONTEXT_SURFACE2D = 0x313371C3,
CELL_GCM_CONTEXT_SWIZZLE2D = 0x31337A73,
};
rsx::blit_engine::context_surface rsx::blit_engine::to_context_surface(u32 in)
{
switch (in)
{
case CELL_GCM_CONTEXT_SURFACE2D: return rsx::blit_engine::context_surface::surface2d;
case CELL_GCM_CONTEXT_SWIZZLE2D: return rsx::blit_engine::context_surface::swizzle2d;
}
throw EXCEPTION("unknow context surface %x", in);
}
rsx::blit_engine::context_dma rsx::blit_engine::to_context_dma(u32 in)
{
switch (in)
{
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT: return rsx::blit_engine::context_dma::to_memory_get_report;
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: return rsx::blit_engine::context_dma::report_location_main;
}
throw EXCEPTION("unknow context dma %x", in);
}
enum
{
CELL_GCM_USER_CLIP_PLANE_DISABLE = 0,
CELL_GCM_USER_CLIP_PLANE_ENABLE_LT = 1,
CELL_GCM_USER_CLIP_PLANE_ENABLE_GE = 2,
};
rsx::user_clip_plane_op rsx::to_user_clip_plane_op(u8 in)
{
switch (in)
{
case CELL_GCM_USER_CLIP_PLANE_DISABLE: return rsx::user_clip_plane_op::disable;
case CELL_GCM_USER_CLIP_PLANE_ENABLE_LT: return rsx::user_clip_plane_op::less_than;
case CELL_GCM_USER_CLIP_PLANE_ENABLE_GE: return rsx::user_clip_plane_op::greather_or_equal;
}
throw EXCEPTION("unknow user clip plane %x", in);
}
// Various parameter pretty printing function
namespace
{

View File

@ -212,6 +212,178 @@ namespace rsx
};
texture_magnify_filter to_texture_magnify_filter(u8 in);
enum class stencil_op : u8
{
keep,
zero,
replace,
incr,
decr,
invert,
incr_wrap,
decr_wrap,
};
stencil_op to_stencil_op(u16 in);
enum class blend_equation : u8
{
add,
min,
max,
substract,
reverse_substract,
reverse_substract_signed,
add_signed,
reverse_add_signed,
};
blend_equation to_blend_equation(u16 in);
enum class blend_factor : u8
{
zero,
one,
src_color,
one_minus_src_color,
dst_color,
one_minus_dst_color,
src_alpha,
one_minus_src_alpha,
dst_alpha,
one_minus_dst_alpha,
src_alpha_saturate,
constant_color,
one_minus_constant_color,
constant_alpha,
one_minus_constant_alpha,
};
blend_factor to_blend_factor(u16 in);
enum class logic_op : u8
{
logic_clear,
logic_and,
logic_and_reverse,
logic_copy,
logic_and_inverted,
logic_noop,
logic_xor,
logic_or,
logic_nor,
logic_equiv,
logic_invert,
logic_or_reverse,
logic_copy_inverted,
logic_or_inverted,
logic_nand,
logic_set,
};
logic_op to_logic_op(u16 in);
enum class front_face : u8
{
cw, /// clockwise
ccw /// counter clockwise
};
front_face to_front_face(u16 in);
enum class cull_face : u8
{
front,
back,
front_and_back,
};
cull_face to_cull_face(u16 in);
enum class user_clip_plane_op : u8
{
disable,
less_than,
greather_or_equal,
};
user_clip_plane_op to_user_clip_plane_op(u8 in);
namespace blit_engine
{
enum class transfer_origin : u8
{
center,
corner,
};
transfer_origin to_transfer_origin(u8 in);
enum class transfer_interpolator : u8
{
zoh,
foh,
};
transfer_interpolator to_transfer_interpolator(u8 in);
enum class transfer_operation : u8
{
srccopy_and,
rop_and,
blend_and,
srccopy,
srccopy_premult,
blend_premult,
};
transfer_operation to_transfer_operation(u8 in);
enum class transfer_source_format : u8
{
a1r5g5b5,
x1r5g5b5,
a8r8g8b8,
x8r8g8b8,
cr8yb8cb8ya8,
yb8cr8ya8cb8,
r5g6b5,
y8,
ay8,
eyb8ecr8eya8ecb8,
ecr8eyb8ecb8eya8,
a8b8g8r8,
x8b8g8r8,
};
transfer_source_format to_transfer_source_format(u8 in);
enum class transfer_destination_format : u8
{
r5g6b5,
a8r8g8b8,
y32,
};
transfer_destination_format to_transfer_destination_format(u8 in);
enum class context_surface : u8
{
surface2d,
swizzle2d,
};
context_surface to_context_surface(u32 in);
enum class context_dma : u8
{
to_memory_get_report,
report_location_main,
};
context_dma to_context_dma(u32 in);
}
}
enum
@ -298,43 +470,6 @@ enum
CELL_GCM_SURFACE_SWIZZLE = 2,
};
enum
{
// Transfer operations
CELL_GCM_TRANSFER_OPERATION_SRCCOPY_AND = 0,
CELL_GCM_TRANSFER_OPERATION_ROP_AND = 1,
CELL_GCM_TRANSFER_OPERATION_BLEND_AND = 2,
CELL_GCM_TRANSFER_OPERATION_SRCCOPY = 3,
CELL_GCM_TRANSFER_OPERATION_SRCCOPY_PREMULT = 4,
CELL_GCM_TRANSFER_OPERATION_BLEND_PREMULT = 5,
CELL_GCM_TRANSFER_ORIGIN_CENTER = 1,
CELL_GCM_TRANSFER_ORIGIN_CORNER = 2,
CELL_GCM_TRANSFER_INTERPOLATOR_ZOH = 0,
CELL_GCM_TRANSFER_INTERPOLATOR_FOH = 1,
// Destination Format conversions
CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 = 4,
CELL_GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8 = 10,
CELL_GCM_TRANSFER_SURFACE_FORMAT_Y32 = 11,
// Source Format conversions
CELL_GCM_TRANSFER_SCALE_FORMAT_A1R5G5B5 = 1,
CELL_GCM_TRANSFER_SCALE_FORMAT_X1R5G5B5 = 2,
CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8 = 3,
CELL_GCM_TRANSFER_SCALE_FORMAT_X8R8G8B8 = 4,
CELL_GCM_TRANSFER_SCALE_FORMAT_CR8YB8CB8YA8 = 5,
CELL_GCM_TRANSFER_SCALE_FORMAT_YB8CR8YA8CB8 = 6,
CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 = 7,
CELL_GCM_TRANSFER_SCALE_FORMAT_Y8 = 8,
CELL_GCM_TRANSFER_SCALE_FORMAT_AY8 = 9,
CELL_GCM_TRANSFER_SCALE_FORMAT_EYB8ECR8EYA8ECB8 = 10,
CELL_GCM_TRANSFER_SCALE_FORMAT_ECR8EYB8ECB8EYA8 = 11,
CELL_GCM_TRANSFER_SCALE_FORMAT_A8B8G8R8 = 12,
CELL_GCM_TRANSFER_SCALE_FORMAT_X8B8G8R8 = 13,
};
enum
{
CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL = 0,
@ -567,10 +702,6 @@ enum
CELL_GCM_TRUE = 1,
CELL_GCM_FALSE = 0,
CELL_GCM_USER_CLIP_PLANE_DISABLE = 0,
CELL_GCM_USER_CLIP_PLANE_ENABLE_LT = 1,
CELL_GCM_USER_CLIP_PLANE_ENABLE_GE = 2,
};
enum
@ -594,10 +725,8 @@ enum
{
CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER = 0xFEED0000, // Local memory
CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER = 0xFEED0001, // Main memory
CELL_GCM_CONTEXT_SURFACE2D = 0x313371C3,
CELL_GCM_CONTEXT_SWIZZLE2D = 0x31337A73,
CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT = 0x66626660,
CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN = 0xBAD68000,
CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT = 0x66626660,
CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN = 0xBAD68000,
CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F,
};

View File

@ -71,6 +71,125 @@ u32 GLGSRender::enable(u32 condition, u32 cap, u32 index)
extern CellGcmContextData current_context;
namespace
{
GLenum comparaison_op(rsx::comparaison_function op)
{
switch (op)
{
case rsx::comparaison_function::never: return GL_NEVER;
case rsx::comparaison_function::less: return GL_LESS;
case rsx::comparaison_function::equal: return GL_EQUAL;
case rsx::comparaison_function::less_or_equal: return GL_LEQUAL;
case rsx::comparaison_function::greater: return GL_GREATER;
case rsx::comparaison_function::not_equal: return GL_NOTEQUAL;
case rsx::comparaison_function::greater_or_equal: return GL_GEQUAL;
case rsx::comparaison_function::always: return GL_ALWAYS;
}
throw;
}
GLenum stencil_op(rsx::stencil_op op)
{
switch (op)
{
case rsx::stencil_op::keep: return GL_KEEP;
case rsx::stencil_op::zero: return GL_ZERO;
case rsx::stencil_op::replace: return GL_REPLACE;
case rsx::stencil_op::incr: return GL_INCR;
case rsx::stencil_op::decr: return GL_DECR;
case rsx::stencil_op::incr_wrap: return GL_INCR_WRAP;
case rsx::stencil_op::decr_wrap: return GL_DECR_WRAP;
}
throw;
}
GLenum blend_equation(rsx::blend_equation op)
{
switch (op)
{
// Note : maybe add is signed on gl
case rsx::blend_equation::add: return GL_FUNC_ADD;
case rsx::blend_equation::min: return GL_MIN;
case rsx::blend_equation::max: return GL_MAX;
case rsx::blend_equation::substract: return GL_FUNC_SUBTRACT;
case rsx::blend_equation::reverse_substract: return GL_FUNC_REVERSE_SUBTRACT;
case rsx::blend_equation::reverse_substract_signed: throw "unsupported";
case rsx::blend_equation::add_signed: throw "unsupported";
case rsx::blend_equation::reverse_add_signed: throw "unsupported";
}
throw;
}
GLenum blend_factor(rsx::blend_factor op)
{
switch (op)
{
case rsx::blend_factor::zero: return GL_ZERO;
case rsx::blend_factor::one: return GL_ONE;
case rsx::blend_factor::src_color: return GL_SRC_COLOR;
case rsx::blend_factor::one_minus_src_color: return GL_ONE_MINUS_SRC_COLOR;
case rsx::blend_factor::dst_color: return GL_DST_COLOR;
case rsx::blend_factor::one_minus_dst_color: return GL_ONE_MINUS_DST_COLOR;
case rsx::blend_factor::src_alpha: return GL_SRC_ALPHA;
case rsx::blend_factor::one_minus_src_alpha: return GL_ONE_MINUS_SRC_ALPHA;
case rsx::blend_factor::dst_alpha: return GL_DST_ALPHA;
case rsx::blend_factor::one_minus_dst_alpha: return GL_ONE_MINUS_DST_ALPHA;
case rsx::blend_factor::src_alpha_saturate: return GL_SRC_ALPHA_SATURATE;
case rsx::blend_factor::constant_color: return GL_CONSTANT_COLOR;
case rsx::blend_factor::one_minus_constant_color: return GL_ONE_MINUS_CONSTANT_COLOR;
case rsx::blend_factor::constant_alpha: return GL_CONSTANT_ALPHA;
case rsx::blend_factor::one_minus_constant_alpha: return GL_ONE_MINUS_CONSTANT_ALPHA;
}
throw;
}
GLenum logic_op(rsx::logic_op op)
{
switch (op)
{
case rsx::logic_op::logic_clear: return GL_CLEAR;
case rsx::logic_op::logic_and: return GL_AND;
case rsx::logic_op::logic_and_reverse: return GL_AND_REVERSE;
case rsx::logic_op::logic_copy: return GL_COPY;
case rsx::logic_op::logic_and_inverted: return GL_AND_INVERTED;
case rsx::logic_op::logic_noop: return GL_NOOP;
case rsx::logic_op::logic_xor: return GL_XOR;
case rsx::logic_op::logic_or : return GL_OR;
case rsx::logic_op::logic_nor: return GL_NOR;
case rsx::logic_op::logic_equiv: return GL_EQUIV;
case rsx::logic_op::logic_invert: return GL_INVERT;
case rsx::logic_op::logic_or_reverse: return GL_OR_REVERSE;
case rsx::logic_op::logic_copy_inverted: return GL_COPY_INVERTED;
case rsx::logic_op::logic_or_inverted: return GL_OR_INVERTED;
case rsx::logic_op::logic_nand: return GL_NAND;
case rsx::logic_op::logic_set: return GL_SET;
}
throw;
}
GLenum front_face(rsx::front_face op)
{
switch (op)
{
case rsx::front_face::cw: return GL_CW;
case rsx::front_face::ccw: return GL_CCW;
}
throw;
}
GLenum cull_face(rsx::cull_face op)
{
switch (op)
{
case rsx::cull_face::front: return GL_FRONT;
case rsx::cull_face::back: return GL_BACK;
case rsx::cull_face::front_and_back: return GL_FRONT_AND_BACK;
}
throw;
}
}
void GLGSRender::begin()
{
rsx::thread::begin();
@ -79,127 +198,110 @@ void GLGSRender::begin()
std::chrono::time_point<std::chrono::system_clock> then = std::chrono::system_clock::now();
u32 color_mask = rsx::method_registers[NV4097_SET_COLOR_MASK];
bool color_mask_b = !!(color_mask & 0xff);
bool color_mask_g = !!((color_mask >> 8) & 0xff);
bool color_mask_r = !!((color_mask >> 16) & 0xff);
bool color_mask_a = !!((color_mask >> 24) & 0xff);
bool color_mask_b = rsx::method_registers.color_mask_b();
bool color_mask_g = rsx::method_registers.color_mask_g();
bool color_mask_r = rsx::method_registers.color_mask_r();
bool color_mask_a = rsx::method_registers.color_mask_a();
__glcheck glColorMask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
__glcheck glDepthMask(rsx::method_registers[NV4097_SET_DEPTH_MASK]);
__glcheck glStencilMask(rsx::method_registers[NV4097_SET_STENCIL_MASK]);
__glcheck glDepthMask(rsx::method_registers.depth_write_enabled());
__glcheck glStencilMask(rsx::method_registers.stencil_mask());
if (__glcheck enable(rsx::method_registers[NV4097_SET_DEPTH_TEST_ENABLE], GL_DEPTH_TEST))
if (__glcheck enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
{
__glcheck glDepthFunc(rsx::method_registers[NV4097_SET_DEPTH_FUNC]);
__glcheck glDepthMask(rsx::method_registers[NV4097_SET_DEPTH_MASK]);
__glcheck glDepthFunc(comparaison_op(rsx::method_registers.depth_func()));
__glcheck glDepthMask(rsx::method_registers.depth_write_enabled());
}
if (glDepthBoundsEXT && (__glcheck enable(rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE], GL_DEPTH_BOUNDS_TEST_EXT)))
if (glDepthBoundsEXT && (__glcheck enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
{
__glcheck glDepthBoundsEXT((f32&)rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_MIN], (f32&)rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_MAX]);
__glcheck glDepthBoundsEXT(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
}
__glcheck glDepthRange((f32&)rsx::method_registers[NV4097_SET_CLIP_MIN], (f32&)rsx::method_registers[NV4097_SET_CLIP_MAX]);
__glcheck enable(rsx::method_registers[NV4097_SET_DITHER_ENABLE], GL_DITHER);
__glcheck glDepthRange(rsx::method_registers.clip_min(), rsx::method_registers.clip_max());
__glcheck enable(rsx::method_registers.dither_enabled(), GL_DITHER);
if (__glcheck enable(rsx::method_registers[NV4097_SET_BLEND_ENABLE], GL_BLEND))
if (__glcheck enable(rsx::method_registers.blend_enabled(), GL_BLEND))
{
u32 sfactor = rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR];
u32 dfactor = rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR];
u16 sfactor_rgb = sfactor;
u16 sfactor_a = sfactor >> 16;
u16 dfactor_rgb = dfactor;
u16 dfactor_a = dfactor >> 16;
__glcheck glBlendFuncSeparate(sfactor_rgb, dfactor_rgb, sfactor_a, dfactor_a);
__glcheck glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_sfactor_a()),
blend_factor(rsx::method_registers.blend_func_dfactor_a()));
if (m_surface.color_format == rsx::surface_color_format::w16z16y16x16) //TODO: check another color formats
{
u32 blend_color = rsx::method_registers[NV4097_SET_BLEND_COLOR];
u32 blend_color2 = rsx::method_registers[NV4097_SET_BLEND_COLOR2];
u16 blend_color_r = blend_color;
u16 blend_color_g = blend_color >> 16;
u16 blend_color_b = blend_color2;
u16 blend_color_a = blend_color2 >> 16;
u16 blend_color_r = rsx::method_registers.blend_color_16b_r();
u16 blend_color_g = rsx::method_registers.blend_color_16b_g();
u16 blend_color_b = rsx::method_registers.blend_color_16b_b();
u16 blend_color_a = rsx::method_registers.blend_color_16b_a();
__glcheck glBlendColor(blend_color_r / 65535.f, blend_color_g / 65535.f, blend_color_b / 65535.f, blend_color_a / 65535.f);
}
else
{
u32 blend_color = rsx::method_registers[NV4097_SET_BLEND_COLOR];
u8 blend_color_r = blend_color;
u8 blend_color_g = blend_color >> 8;
u8 blend_color_b = blend_color >> 16;
u8 blend_color_a = blend_color >> 24;
u8 blend_color_r = rsx::method_registers.blend_color_8b_r();
u8 blend_color_g = rsx::method_registers.blend_color_8b_g();
u8 blend_color_b = rsx::method_registers.blend_color_8b_b();
u8 blend_color_a = rsx::method_registers.blend_color_8b_a();
__glcheck glBlendColor(blend_color_r / 255.f, blend_color_g / 255.f, blend_color_b / 255.f, blend_color_a / 255.f);
}
u32 equation = rsx::method_registers[NV4097_SET_BLEND_EQUATION];
u16 equation_rgb = equation;
u16 equation_a = equation >> 16;
__glcheck glBlendEquationSeparate(equation_rgb, equation_a);
__glcheck glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
blend_equation(rsx::method_registers.blend_equation_a()));
}
if (__glcheck enable(rsx::method_registers[NV4097_SET_STENCIL_TEST_ENABLE], GL_STENCIL_TEST))
if (__glcheck enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
{
__glcheck glStencilFunc(rsx::method_registers[NV4097_SET_STENCIL_FUNC], rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF],
rsx::method_registers[NV4097_SET_STENCIL_FUNC_MASK]);
__glcheck glStencilOp(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL], rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL],
rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]);
__glcheck glStencilFunc(comparaison_op(rsx::method_registers.stencil_func()), rsx::method_registers.stencil_func_ref(),
rsx::method_registers.stencil_func_mask());
__glcheck glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
stencil_op(rsx::method_registers.stencil_op_zpass()));
if (rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE])
{
__glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_MASK]);
__glcheck glStencilFuncSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC],
rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_REF], rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_MASK]);
__glcheck glStencilOpSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL],
rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL], rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS]);
if (rsx::method_registers.two_sided_stencil_test_enabled()) {
__glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
__glcheck glStencilFuncSeparate(GL_BACK, comparaison_op(rsx::method_registers.back_stencil_func()),
rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask());
__glcheck glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass()));
}
}
if (u32 blend_mrt = rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT])
{
__glcheck enable(blend_mrt & 2, GL_BLEND, 1);
__glcheck enable(blend_mrt & 4, GL_BLEND, 2);
__glcheck enable(blend_mrt & 8, GL_BLEND, 3);
}
__glcheck enable(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
__glcheck enable(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
__glcheck enable(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
if (__glcheck enable(rsx::method_registers[NV4097_SET_LOGIC_OP_ENABLE], GL_COLOR_LOGIC_OP))
if (__glcheck enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
{
__glcheck glLogicOp(rsx::method_registers[NV4097_SET_LOGIC_OP]);
__glcheck glLogicOp(logic_op(rsx::method_registers.logic_operation()));
}
u32 line_width = rsx::method_registers[NV4097_SET_LINE_WIDTH];
__glcheck glLineWidth((line_width >> 3) + (line_width & 7) / 8.f);
__glcheck enable(rsx::method_registers[NV4097_SET_LINE_SMOOTH_ENABLE], GL_LINE_SMOOTH);
__glcheck glLineWidth(rsx::method_registers.line_width());
__glcheck enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
//TODO
//NV4097_SET_ANISO_SPREAD
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_POINT_ENABLE], GL_POLYGON_OFFSET_POINT);
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_LINE_ENABLE], GL_POLYGON_OFFSET_LINE);
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_FILL_ENABLE], GL_POLYGON_OFFSET_FILL);
__glcheck enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
__glcheck enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
__glcheck enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
__glcheck glPolygonOffset((f32&)rsx::method_registers[NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR],
(f32&)rsx::method_registers[NV4097_SET_POLYGON_OFFSET_BIAS]);
__glcheck glPolygonOffset(rsx::method_registers.poly_offset_scale(),
rsx::method_registers.poly_offset_bias());
//NV4097_SET_SPECULAR_ENABLE
//NV4097_SET_TWO_SIDE_LIGHT_EN
//NV4097_SET_FLAT_SHADE_OP
//NV4097_SET_EDGE_FLAG
if (__glcheck enable(rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE], GL_CULL_FACE))
if (__glcheck enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
{
__glcheck glCullFace(rsx::method_registers[NV4097_SET_CULL_FACE]);
__glcheck glCullFace(cull_face(rsx::method_registers.cull_face_mode()));
}
__glcheck glFrontFace(get_front_face_ccw(rsx::method_registers[NV4097_SET_FRONT_FACE] ^ 1));
__glcheck glFrontFace(front_face(rsx::method_registers.front_face_mode()));
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_SMOOTH_ENABLE], GL_POLYGON_SMOOTH);
__glcheck enable(rsx::method_registers.poly_smooth_enabled(), GL_POLYGON_SMOOTH);
//NV4097_SET_COLOR_KEY_COLOR
//NV4097_SET_SHADER_CONTROL
@ -207,9 +309,9 @@ void GLGSRender::begin()
//NV4097_SET_ANTI_ALIASING_CONTROL
//NV4097_SET_CLIP_ID_TEST_ENABLE
if (__glcheck enable(rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE], GL_PRIMITIVE_RESTART))
if (__glcheck enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
{
__glcheck glPrimitiveRestartIndex(rsx::method_registers[NV4097_SET_RESTART_INDEX]);
__glcheck glPrimitiveRestartIndex(rsx::method_registers.restart_index());
}
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
@ -252,15 +354,14 @@ void GLGSRender::end()
return;
}
u32 clip_plane_control = rsx::method_registers[NV4097_SET_USER_CLIP_PLANE_CONTROL];
u8 clip_plane_0 = clip_plane_control & 0xf;
u8 clip_plane_1 = (clip_plane_control >> 4) & 0xf;
u8 clip_plane_2 = (clip_plane_control >> 8) & 0xf;
u8 clip_plane_3 = (clip_plane_control >> 12) & 0xf;
u8 clip_plane_4 = (clip_plane_control >> 16) & 0xf;
u8 clip_plane_5 = (clip_plane_control >> 20) & 0xf;
rsx::user_clip_plane_op clip_plane_0 = rsx::method_registers.clip_plane_0_enabled();
rsx::user_clip_plane_op clip_plane_1 = rsx::method_registers.clip_plane_1_enabled();
rsx::user_clip_plane_op clip_plane_2 = rsx::method_registers.clip_plane_2_enabled();
rsx::user_clip_plane_op clip_plane_3 = rsx::method_registers.clip_plane_3_enabled();
rsx::user_clip_plane_op clip_plane_4 = rsx::method_registers.clip_plane_4_enabled();
rsx::user_clip_plane_op clip_plane_5 = rsx::method_registers.clip_plane_5_enabled();
auto set_clip_plane_control = [&](int index, u8 control)
auto set_clip_plane_control = [&](int index, rsx::user_clip_plane_op control)
{
int value = 0;
int location;
@ -271,15 +372,15 @@ void GLGSRender::end()
default:
LOG_ERROR(RSX, "bad clip plane control (0x%x)", control);
case CELL_GCM_USER_CLIP_PLANE_DISABLE:
case rsx::user_clip_plane_op::disable:
value = 0;
break;
case CELL_GCM_USER_CLIP_PLANE_ENABLE_GE:
case rsx::user_clip_plane_op::greather_or_equal:
value = 1;
break;
case CELL_GCM_USER_CLIP_PLANE_ENABLE_LT:
case rsx::user_clip_plane_op::less_than:
value = -1;
break;
}
@ -307,7 +408,7 @@ void GLGSRender::end()
int location;
if (m_program->uniforms.has_location("ftexture" + std::to_string(i), &location))
{
if (!textures[i].enabled())
if (!rsx::method_registers.fragment_textures[i].enabled())
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
@ -316,18 +417,18 @@ void GLGSRender::end()
continue;
}
m_gl_textures[i].set_target(get_gl_target_for_texture(textures[i]));
m_gl_textures[i].set_target(get_gl_target_for_texture(rsx::method_registers.fragment_textures[i]));
__glcheck m_gl_texture_cache.upload_texture(i, textures[i], m_gl_textures[i], m_rtts);
__glcheck m_gl_texture_cache.upload_texture(i, rsx::method_registers.fragment_textures[i], m_gl_textures[i], m_rtts);
__glcheck glProgramUniform1i(m_program->id(), location, i);
if (m_program->uniforms.has_location("ftexture" + std::to_string(i) + "_cm", &location))
{
if (textures[i].format() & CELL_GCM_TEXTURE_UN)
if (rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN)
{
u32 width = std::max<u32>(textures[i].width(), 1);
u32 height = std::max<u32>(textures[i].height(), 1);
u32 depth = std::max<u32>(textures[i].depth(), 1);
u32 width = std::max<u32>(rsx::method_registers.fragment_textures[i].width(), 1);
u32 height = std::max<u32>(rsx::method_registers.fragment_textures[i].height(), 1);
u32 depth = std::max<u32>(rsx::method_registers.fragment_textures[i].depth(), 1);
glProgramUniform4f(m_program->id(), location, 1.f / width, 1.f / height, 1.f / depth, 1.0f);
}
@ -340,7 +441,7 @@ void GLGSRender::end()
int location;
if (m_program->uniforms.has_location("vtexture" + std::to_string(i), &location))
{
if (!textures[i].enabled())
if (!rsx::method_registers.fragment_textures[i].enabled())
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
@ -349,18 +450,18 @@ void GLGSRender::end()
continue;
}
m_gl_vertex_textures[i].set_target(get_gl_target_for_texture(vertex_textures[i]));
m_gl_vertex_textures[i].set_target(get_gl_target_for_texture(rsx::method_registers.vertex_textures[i]));
__glcheck m_gl_texture_cache.upload_texture(i, vertex_textures[i], m_gl_vertex_textures[i], m_rtts);
__glcheck m_gl_texture_cache.upload_texture(i, rsx::method_registers.vertex_textures[i], m_gl_vertex_textures[i], m_rtts);
__glcheck glProgramUniform1i(m_program->id(), location, i);
if (m_program->uniforms.has_location("vtexture" + std::to_string(i) + "_cm", &location))
{
if (textures[i].format() & CELL_GCM_TEXTURE_UN)
if (rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN)
{
u32 width = std::max<u32>(textures[i].width(), 1);
u32 height = std::max<u32>(textures[i].height(), 1);
u32 depth = std::max<u32>(textures[i].depth(), 1);
u32 width = std::max<u32>(rsx::method_registers.fragment_textures[i].width(), 1);
u32 height = std::max<u32>(rsx::method_registers.fragment_textures[i].height(), 1);
u32 depth = std::max<u32>(rsx::method_registers.fragment_textures[i].depth(), 1);
glProgramUniform4f(m_program->id(), location, 1.f / width, 1.f / height, 1.f / depth, 1.0f);
}
@ -381,7 +482,7 @@ void GLGSRender::end()
if (draw_command == rsx::draw_command::indexed)
{
rsx::index_array_type indexed_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
rsx::index_array_type indexed_type = rsx::method_registers.index_type();
if (indexed_type == rsx::index_array_type::u32)
{
@ -415,24 +516,17 @@ void GLGSRender::end()
void GLGSRender::set_viewport()
{
u32 viewport_horizontal = rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL];
u32 viewport_vertical = rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL];
u16 viewport_x = rsx::method_registers.viewport_origin_x();
u16 viewport_y = rsx::method_registers.viewport_origin_y();
u16 viewport_w = rsx::method_registers.viewport_width();
u16 viewport_h = rsx::method_registers.viewport_height();
u16 viewport_x = viewport_horizontal & 0xffff;
u16 viewport_y = viewport_vertical & 0xffff;
u16 viewport_w = viewport_horizontal >> 16;
u16 viewport_h = viewport_vertical >> 16;
u16 scissor_x = rsx::method_registers.scissor_origin_x();
u16 scissor_w = rsx::method_registers.scissor_width();
u16 scissor_y = rsx::method_registers.scissor_origin_y();
u16 scissor_h = rsx::method_registers.scissor_height();
u32 scissor_horizontal = rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL];
u32 scissor_vertical = rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL];
u16 scissor_x = scissor_horizontal;
u16 scissor_w = scissor_horizontal >> 16;
u16 scissor_y = scissor_vertical;
u16 scissor_h = scissor_vertical >> 16;
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
rsx::window_origin shader_window_origin = rsx::method_registers.shader_window_origin();
if (shader_window_origin == rsx::window_origin::bottom)
{
@ -441,7 +535,7 @@ void GLGSRender::set_viewport()
}
else
{
u16 shader_window_height = shader_window & 0xfff;
u16 shader_window_height = rsx::method_registers.shader_window_height();
__glcheck glViewport(viewport_x, shader_window_height - viewport_y - viewport_h + 1, viewport_w, viewport_h);
__glcheck glScissor(scissor_x, shader_window_height - scissor_y - scissor_h + 1, scissor_w, scissor_h);
@ -519,10 +613,7 @@ void GLGSRender::on_exit()
void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
{
//LOG_NOTICE(Log::RSX, "nv4097_clear_surface(0x%x)", arg);
if (!rsx::method_registers[NV4097_SET_SURFACE_FORMAT])
{
return;
}
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
if ((arg & 0xf3) == 0)
{
@ -543,13 +634,13 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
GLbitfield mask = 0;
rsx::surface_depth_format surface_depth_format = rsx::to_surface_depth_format((rsx::method_registers[NV4097_SET_SURFACE_FORMAT] >> 5) & 0x7);
rsx::surface_depth_format surface_depth_format = rsx::method_registers.surface_depth_fmt();
if (arg & 0x1)
{
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
u32 clear_depth = rsx::method_registers.z_clear_value();
glDepthMask(GL_TRUE);
glClearDepth(double(clear_depth) / max_depth_value);
@ -558,9 +649,9 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
if (surface_depth_format == rsx::surface_depth_format::z24s8 && (arg & 0x2))
{
u8 clear_stencil = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] & 0xff;
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
__glcheck glStencilMask(rsx::method_registers[NV4097_SET_STENCIL_MASK]);
__glcheck glStencilMask(rsx::method_registers.stencil_mask());
glClearStencil(clear_stencil);
mask |= GLenum(gl::buffers::stencil);
@ -568,11 +659,10 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
if (arg & 0xf0)
{
u32 clear_color = rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE];
u8 clear_a = clear_color >> 24;
u8 clear_r = clear_color >> 16;
u8 clear_g = clear_color >> 8;
u8 clear_b = clear_color;
u8 clear_a = rsx::method_registers.clear_color_a();
u8 clear_r = rsx::method_registers.clear_color_r();
u8 clear_g = rsx::method_registers.clear_color_g();
u8 clear_b = rsx::method_registers.clear_color_b();
glColorMask(((arg & 0x20) ? 1 : 0), ((arg & 0x40) ? 1 : 0), ((arg & 0x80) ? 1 : 0), ((arg & 0x10) ? 1 : 0));
glClearColor(clear_r / 255.f, clear_g / 255.f, clear_b / 255.f, clear_a / 255.f);
@ -638,18 +728,13 @@ static void fill_matrix_buffer(glsl_matrix_buffer *buffer)
rsx::fill_viewport_matrix(buffer->viewport_matrix, true);
rsx::fill_window_matrix(buffer->window_matrix, true);
u32 viewport_horizontal = rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL];
u32 viewport_vertical = rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL];
f32 viewport_x = rsx::method_registers.viewport_origin_x();
f32 viewport_y = rsx::method_registers.viewport_origin_y();
f32 viewport_w = rsx::method_registers.viewport_width();
f32 viewport_h = rsx::method_registers.viewport_height();
f32 viewport_x = f32(viewport_horizontal & 0xffff);
f32 viewport_y = f32(viewport_vertical & 0xffff);
f32 viewport_w = f32(viewport_horizontal >> 16);
f32 viewport_h = f32(viewport_vertical >> 16);
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
u16 shader_window_height = shader_window & 0xfff;
rsx::window_origin shader_window_origin = rsx::method_registers.shader_window_origin();
u16 shader_window_height = rsx::method_registers.shader_window_height();
f32 left = viewport_x;
f32 right = viewport_x + viewport_w;
@ -683,10 +768,11 @@ static void fill_matrix_buffer(glsl_matrix_buffer *buffer)
static void fill_fragment_state_buffer(glsl_fragment_state_buffer *buffer)
{
std::memcpy(&buffer->fog_param0, rsx::method_registers + NV4097_SET_FOG_PARAMS, sizeof(float) * 2);
const float fog_params[2] = { rsx::method_registers.fog_params_0(), rsx::method_registers.fog_params_1() };
std::memcpy(&buffer->fog_param0, fog_params, sizeof(float) * 2);
buffer->alpha_test = rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE];
buffer->alpha_ref = rsx::method_registers[NV4097_SET_ALPHA_REF] / 255.f;
buffer->alpha_test = rsx::method_registers.alpha_test_enabled();
buffer->alpha_ref = rsx::method_registers.alpha_ref() / 255.f;
}
bool GLGSRender::load_program()

View File

@ -78,10 +78,8 @@ u8 rsx::internals::get_pixel_size(rsx::surface_depth_format format)
void GLGSRender::init_buffers(bool skip_reading)
{
u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT];
u32 clip_horizontal = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
u32 clip_vertical = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
u16 clip_horizontal = rsx::method_registers.surface_clip_width();
u16 clip_vertical = rsx::method_registers.surface_clip_height();
set_viewport();
@ -97,8 +95,8 @@ void GLGSRender::init_buffers(bool skip_reading)
LOG_NOTICE(RSX, "render to -> 0x%x", get_color_surface_addresses()[0]);
}
m_rtts.prepare_render_target(nullptr, surface_format, clip_horizontal, clip_vertical,
rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]),
m_rtts.prepare_render_target(nullptr, rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(), clip_horizontal, clip_vertical,
rsx::method_registers.surface_color_target(),
get_color_surface_addresses(), get_zeta_surface_address());
draw_fbo.recreate();
@ -119,7 +117,7 @@ void GLGSRender::init_buffers(bool skip_reading)
__glcheck draw_fbo.check();
//HACK: read_buffer shouldn't be there
switch (rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
switch (rsx::method_registers.surface_color_target())
{
case rsx::surface_target::none: break;
@ -152,20 +150,49 @@ void GLGSRender::init_buffers(bool skip_reading)
std::array<std::vector<gsl::byte>, 4> GLGSRender::copy_render_targets_to_memory()
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
return m_rtts.get_render_targets_data(surface.color_format, clip_w, clip_h);
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
return m_rtts.get_render_targets_data(rsx::method_registers.surface_color(), clip_w, clip_h);
}
std::array<std::vector<gsl::byte>, 2> GLGSRender::copy_depth_stencil_buffer_to_memory()
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
return m_rtts.get_depth_stencil_data(surface.depth_format, clip_w, clip_h);
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
return m_rtts.get_depth_stencil_data(rsx::method_registers.surface_depth_fmt(), clip_w, clip_h);
}
namespace
{
std::array<u32, 4> get_offsets()
{
return{
rsx::method_registers.surface_a_offset(),
rsx::method_registers.surface_b_offset(),
rsx::method_registers.surface_c_offset(),
rsx::method_registers.surface_d_offset(),
};
}
std::array<u32, 4> get_locations()
{
return{
rsx::method_registers.surface_a_dma(),
rsx::method_registers.surface_b_dma(),
rsx::method_registers.surface_c_dma(),
rsx::method_registers.surface_d_dma(),
};
}
std::array<u32, 4> get_pitchs()
{
return{
rsx::method_registers.surface_a_pitch(),
rsx::method_registers.surface_b_pitch(),
rsx::method_registers.surface_c_pitch(),
rsx::method_registers.surface_d_pitch(),
};
}
}
void GLGSRender::read_buffers()
@ -181,14 +208,18 @@ void GLGSRender::read_buffers()
auto read_color_buffers = [&](int index, int count)
{
u32 width = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
u32 height = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
u32 width = rsx::method_registers.surface_clip_width();
u32 height = rsx::method_registers.surface_clip_height();
const std::array<u32, 4> offsets = get_offsets();
const std::array<u32, 4 > locations = get_locations();
const std::array<u32, 4 > pitchs = get_pitchs();
for (int i = index; i < index + count; ++i)
{
u32 offset = rsx::method_registers[rsx::internals::mr_color_offset[i]];
u32 location = rsx::method_registers[rsx::internals::mr_color_dma[i]];
u32 pitch = rsx::method_registers[rsx::internals::mr_color_pitch[i]];
u32 offset = offsets[i];
u32 location = locations[i];
u32 pitch = pitchs[i];
if (pitch <= 64)
continue;
@ -219,7 +250,7 @@ void GLGSRender::read_buffers()
}
};
switch (rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
switch (rsx::method_registers.surface_color_target())
{
case rsx::surface_target::none:
break;
@ -249,12 +280,12 @@ void GLGSRender::read_buffers()
if (g_cfg_rsx_read_depth_buffer)
{
//TODO: use pitch
u32 pitch = rsx::method_registers[NV4097_SET_SURFACE_PITCH_Z];
u32 pitch = rsx::method_registers.surface_z_pitch();
if (pitch <= 64)
return;
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
u32 depth_address = rsx::get_address(rsx::method_registers.surface_z_offset(), rsx::method_registers.surface_z_dma());
bool in_cache = m_gl_texture_cache.explicit_writeback((*std::get<1>(m_rtts.m_bound_depth_stencil)), depth_address, pitch);
if (in_cache)
@ -269,7 +300,7 @@ void GLGSRender::read_buffers()
__glcheck pbo_depth.create(m_surface.width * m_surface.height * pixel_size);
__glcheck pbo_depth.map([&](GLubyte* pixels)
{
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
u32 depth_address = rsx::get_address(rsx::method_registers.surface_z_offset(), rsx::method_registers.surface_z_dma());
if (m_surface.depth_format == rsx::surface_depth_format::z16)
{
@ -309,14 +340,18 @@ void GLGSRender::write_buffers()
auto write_color_buffers = [&](int index, int count)
{
u32 width = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
u32 height = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
u32 width = rsx::method_registers.surface_clip_width();
u32 height = rsx::method_registers.surface_clip_height();
std::array<u32, 4> offsets = get_offsets();
const std::array<u32, 4 > locations = get_locations();
const std::array<u32, 4 > pitchs = get_pitchs();
for (int i = index; i < index + count; ++i)
{
u32 offset = rsx::method_registers[rsx::internals::mr_color_offset[i]];
u32 location = rsx::method_registers[rsx::internals::mr_color_dma[i]];
u32 pitch = rsx::method_registers[rsx::internals::mr_color_pitch[i]];
u32 offset = offsets[i];
u32 location = locations[i];
u32 pitch = pitchs[i];
if (pitch <= 64)
continue;
@ -334,7 +369,7 @@ void GLGSRender::write_buffers()
}
};
switch (rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
switch (rsx::method_registers.surface_color_target())
{
case rsx::surface_target::none:
break;
@ -364,13 +399,13 @@ void GLGSRender::write_buffers()
if (g_cfg_rsx_write_depth_buffer)
{
//TODO: use pitch
u32 pitch = rsx::method_registers[NV4097_SET_SURFACE_PITCH_Z];
u32 pitch = rsx::method_registers.surface_z_pitch();
if (pitch <= 64)
return;
auto depth_format = rsx::internals::surface_depth_format_to_gl(m_surface.depth_format);
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
u32 depth_address = rsx::get_address(rsx::method_registers.surface_z_offset(), rsx::method_registers.surface_z_dma());
u32 range = std::get<1>(m_rtts.m_bound_depth_stencil)->width() * std::get<1>(m_rtts.m_bound_depth_stencil)->height() * 2;
if (m_surface.depth_format != rsx::surface_depth_format::z16) range *= 2;

View File

@ -42,30 +42,6 @@ namespace rsx
color_format surface_color_format_to_gl(rsx::surface_color_format color_format);
depth_format surface_depth_format_to_gl(rsx::surface_depth_format depth_format);
u8 get_pixel_size(rsx::surface_depth_format format);
const u32 mr_color_offset[rsx::limits::color_buffers_count] =
{
NV4097_SET_SURFACE_COLOR_AOFFSET,
NV4097_SET_SURFACE_COLOR_BOFFSET,
NV4097_SET_SURFACE_COLOR_COFFSET,
NV4097_SET_SURFACE_COLOR_DOFFSET
};
const u32 mr_color_dma[rsx::limits::color_buffers_count] =
{
NV4097_SET_CONTEXT_DMA_COLOR_A,
NV4097_SET_CONTEXT_DMA_COLOR_B,
NV4097_SET_CONTEXT_DMA_COLOR_C,
NV4097_SET_CONTEXT_DMA_COLOR_D
};
const u32 mr_color_pitch[rsx::limits::color_buffers_count] =
{
NV4097_SET_SURFACE_PITCH_A,
NV4097_SET_SURFACE_PITCH_B,
NV4097_SET_SURFACE_PITCH_C,
NV4097_SET_SURFACE_PITCH_D
};
}
}

View File

@ -164,7 +164,7 @@ u32 GLGSRender::set_vertex_buffer()
std::chrono::time_point<std::chrono::system_clock> then = std::chrono::system_clock::now();
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
u32 input_mask = rsx::method_registers.vertex_attrib_input_mask();
u32 min_index = 0, max_index = 0;
u32 max_vertex_attrib_size = 0;
u32 offset_in_index_buffer = 0;
@ -176,7 +176,7 @@ u32 GLGSRender::set_vertex_buffer()
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
if (vertex_arrays_info[index].size || register_vertex_info[index].size)
if (rsx::method_registers.vertex_arrays_info[index].size || rsx::method_registers.register_vertex_info[index].size)
{
max_vertex_attrib_size += 16;
}
@ -184,7 +184,7 @@ u32 GLGSRender::set_vertex_buffer()
if (draw_command == rsx::draw_command::indexed)
{
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
for (const auto& first_count : first_count_commands)
{
@ -212,7 +212,7 @@ u32 GLGSRender::set_vertex_buffer()
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
const auto &info = vertex_arrays_info[i];
const auto &info = rsx::method_registers.vertex_arrays_info[i];
if (!info.size) continue;
offsets[i] = stride;
@ -224,7 +224,7 @@ u32 GLGSRender::set_vertex_buffer()
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
auto &vertex_info = vertex_arrays_info[index];
auto &vertex_info = rsx::method_registers.vertex_arrays_info[index];
int location;
if (!m_program->uniforms.has_location(rsx::vertex_program::input_attrib_names[index] + "_buffer", &location))
@ -307,9 +307,9 @@ u32 GLGSRender::set_vertex_buffer()
continue;
}
if (vertex_arrays_info[index].size > 0)
if (rsx::method_registers.vertex_arrays_info[index].size > 0)
{
auto &vertex_info = vertex_arrays_info[index];
auto &vertex_info = rsx::method_registers.vertex_arrays_info[index];
// Fill vertex_array
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
@ -322,8 +322,8 @@ u32 GLGSRender::set_vertex_buffer()
u32 buffer_offset = 0;
// Get source pointer
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 base_offset = rsx::method_registers.vertex_data_base_offset();
u32 offset = rsx::method_registers.vertex_arrays_info[index].offset();
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address));
@ -361,10 +361,10 @@ u32 GLGSRender::set_vertex_buffer()
//Link texture to uniform
m_program->uniforms.texture(location, index + texture_index_offset, texture);
}
else if (register_vertex_info[index].size > 0)
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
auto &vertex_data = register_vertex_data[index];
auto &vertex_info = register_vertex_info[index];
auto &vertex_data = rsx::method_registers.register_vertex_data[index];
auto &vertex_info = rsx::method_registers.register_vertex_info[index];
switch (vertex_info.type)
{

View File

@ -6,63 +6,68 @@
namespace rsx
{
texture::texture(u8 idx, std::array<u32, 0x10000 / 4> &r) : m_index(idx), registers(r)
{
}
void texture::init(u8 index)
{
m_index = index;
// Offset
method_registers[NV4097_SET_TEXTURE_OFFSET + (m_index * 8)] = 0;
registers[NV4097_SET_TEXTURE_OFFSET + (m_index * 8)] = 0;
// Format
method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] = 0;
registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] = 0;
// Address
method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] =
registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] =
((/*wraps*/1) | ((/*anisoBias*/0) << 4) | ((/*wrapt*/1) << 8) | ((/*unsignedRemap*/0) << 12) |
((/*wrapr*/3) << 16) | ((/*gamma*/0) << 20) | ((/*signedRemap*/0) << 24) | ((/*zfunc*/0) << 28));
// Control0
method_registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] =
registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] =
(((/*alphakill*/0) << 2) | (/*maxaniso*/0) << 4) | ((/*maxlod*/0xc00) << 7) | ((/*minlod*/0) << 19) | ((/*enable*/0) << 31);
// Control1
method_registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)] = 0xE4;
registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)] = 0xE4;
// Filter
method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] =
registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] =
((/*bias*/0) | ((/*conv*/1) << 13) | ((/*min*/5) << 16) | ((/*mag*/2) << 24)
| ((/*as*/0) << 28) | ((/*rs*/0) << 29) | ((/*gs*/0) << 30) | ((/*bs*/0) << 31));
// Image Rect
method_registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)] = (/*height*/1) | ((/*width*/1) << 16);
registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)] = (/*height*/1) | ((/*width*/1) << 16);
// Border Color
method_registers[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index * 8)] = 0;
registers[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index * 8)] = 0;
}
u32 texture::offset() const
{
return method_registers[NV4097_SET_TEXTURE_OFFSET + (m_index * 8)];
return registers[NV4097_SET_TEXTURE_OFFSET + (m_index * 8)];
}
u8 texture::location() const
{
return (method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] & 0x3) - 1;
return (registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] & 0x3) - 1;
}
bool texture::cubemap() const
{
return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 2) & 0x1);
return ((registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 2) & 0x1);
}
u8 texture::border_type() const
{
return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 3) & 0x1);
return ((registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 3) & 0x1);
}
rsx::texture_dimension texture::dimension() const
{
return rsx::to_texture_dimension((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf);
return rsx::to_texture_dimension((registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf);
}
rsx::texture_dimension_extended texture::get_extended_texture_dimension() const
@ -79,7 +84,7 @@ namespace rsx
u8 texture::format() const
{
return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 8) & 0xff);
return ((registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 8) & 0xff);
}
bool texture::is_compressed_format() const
@ -94,7 +99,7 @@ namespace rsx
u16 texture::mipmap() const
{
return ((method_registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff);
return ((registers[NV4097_SET_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff);
}
u16 texture::get_exact_mipmap_count() const
@ -112,137 +117,142 @@ namespace rsx
rsx::texture_wrap_mode texture::wrap_s() const
{
return rsx::to_texture_wrap_mode((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)]) & 0xf);
return rsx::to_texture_wrap_mode((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)]) & 0xf);
}
rsx::texture_wrap_mode texture::wrap_t() const
{
return rsx::to_texture_wrap_mode((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 8) & 0xf);
return rsx::to_texture_wrap_mode((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 8) & 0xf);
}
rsx::texture_wrap_mode texture::wrap_r() const
{
return rsx::to_texture_wrap_mode((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 16) & 0xf);
return rsx::to_texture_wrap_mode((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 16) & 0xf);
}
u8 texture::unsigned_remap() const
{
return ((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf);
return ((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf);
}
u8 texture::zfunc() const
{
return ((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 28) & 0xf);
return ((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 28) & 0xf);
}
u8 texture::gamma() const
{
return ((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 20) & 0xf);
return ((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 20) & 0xf);
}
u8 texture::aniso_bias() const
{
return ((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 4) & 0xf);
return ((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 4) & 0xf);
}
u8 texture::signed_remap() const
{
return ((method_registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 24) & 0xf);
return ((registers[NV4097_SET_TEXTURE_ADDRESS + (m_index * 8)] >> 24) & 0xf);
}
bool texture::enabled() const
{
return location() <= 1 && ((method_registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1);
return location() <= 1 && ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1);
}
u16 texture::min_lod() const
{
return ((method_registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff);
return ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff);
}
u16 texture::max_lod() const
{
return ((method_registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff);
return ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff);
}
rsx::texture_max_anisotropy texture::max_aniso() const
{
return rsx::to_texture_max_anisotropy((method_registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7);
return rsx::to_texture_max_anisotropy((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7);
}
bool texture::alpha_kill_enabled() const
{
return ((method_registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 2) & 0x1);
return ((registers[NV4097_SET_TEXTURE_CONTROL0 + (m_index * 8)] >> 2) & 0x1);
}
u32 texture::remap() const
{
return (method_registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]);
return (registers[NV4097_SET_TEXTURE_CONTROL1 + (m_index * 8)]);
}
float texture::bias() const
{
return float(f16((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff));
return float(f16((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff));
}
rsx::texture_minify_filter texture::min_filter() const
{
return rsx::to_texture_minify_filter((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7);
return rsx::to_texture_minify_filter((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7);
}
rsx::texture_magnify_filter texture::mag_filter() const
{
return rsx::to_texture_magnify_filter((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7);
return rsx::to_texture_magnify_filter((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7);
}
u8 texture::convolution_filter() const
{
return ((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf);
return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf);
}
bool texture::a_signed() const
{
return ((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1);
return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1);
}
bool texture::r_signed() const
{
return ((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 29) & 0x1);
return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 29) & 0x1);
}
bool texture::g_signed() const
{
return ((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 30) & 0x1);
return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 30) & 0x1);
}
bool texture::b_signed() const
{
return ((method_registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 31) & 0x1);
return ((registers[NV4097_SET_TEXTURE_FILTER + (m_index * 8)] >> 31) & 0x1);
}
u16 texture::width() const
{
return ((method_registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)] >> 16) & 0xffff);
return ((registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)] >> 16) & 0xffff);
}
u16 texture::height() const
{
return ((method_registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)]) & 0xffff);
return ((registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)]) & 0xffff);
}
u32 texture::border_color() const
{
return method_registers[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index * 8)];
return registers[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index * 8)];
}
u16 texture::depth() const
{
return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] >> 20;
return registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] >> 20;
}
u32 texture::pitch() const
{
return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] & 0xfffff;
return registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] & 0xfffff;
}
vertex_texture::vertex_texture(u8 idx, std::array<u32, 0x10000 / 4> &r) : m_index(idx), registers(r)
{
}
void vertex_texture::init(u8 index)
@ -250,58 +260,58 @@ namespace rsx
m_index = index;
// Offset
method_registers[NV4097_SET_VERTEX_TEXTURE_OFFSET + (m_index * 8)] = 0;
registers[NV4097_SET_VERTEX_TEXTURE_OFFSET + (m_index * 8)] = 0;
// Format
method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] = 0;
registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] = 0;
// Address
method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] =
registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] =
((/*wraps*/1) | ((/*anisoBias*/0) << 4) | ((/*wrapt*/1) << 8) | ((/*unsignedRemap*/0) << 12) |
((/*wrapr*/3) << 16) | ((/*gamma*/0) << 20) | ((/*signedRemap*/0) << 24) | ((/*zfunc*/0) << 28));
// Control0
method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] =
registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] =
(((/*alphakill*/0) << 2) | (/*maxaniso*/0) << 4) | ((/*maxlod*/0xc00) << 7) | ((/*minlod*/0) << 19) | ((/*enable*/0) << 31);
// Control1
//method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL1 + (m_index * 8)] = 0xE4;
//registers[NV4097_SET_VERTEX_TEXTURE_CONTROL1 + (m_index * 8)] = 0xE4;
// Filter
method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] =
registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] =
((/*bias*/0) | ((/*conv*/1) << 13) | ((/*min*/5) << 16) | ((/*mag*/2) << 24)
| ((/*as*/0) << 28) | ((/*rs*/0) << 29) | ((/*gs*/0) << 30) | ((/*bs*/0) << 31));
// Image Rect
method_registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)] = (/*height*/1) | ((/*width*/1) << 16);
registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)] = (/*height*/1) | ((/*width*/1) << 16);
// Border Color
method_registers[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 8)] = 0;
registers[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 8)] = 0;
}
u32 vertex_texture::offset() const
{
return method_registers[NV4097_SET_VERTEX_TEXTURE_OFFSET + (m_index * 8)];
return registers[NV4097_SET_VERTEX_TEXTURE_OFFSET + (m_index * 8)];
}
u8 vertex_texture::location() const
{
return (method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] & 0x3) - 1;
return (registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] & 0x3) - 1;
}
bool vertex_texture::cubemap() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 2) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 2) & 0x1);
}
u8 vertex_texture::border_type() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 3) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 3) & 0x1);
}
rsx::texture_dimension vertex_texture::dimension() const
{
return rsx::to_texture_dimension((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf);
return rsx::to_texture_dimension((registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 4) & 0xf);
}
rsx::texture_dimension_extended vertex_texture::get_extended_texture_dimension() const
@ -318,12 +328,12 @@ namespace rsx
u8 vertex_texture::format() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 8) & 0xff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 8) & 0xff);
}
u16 vertex_texture::mipmap() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FORMAT + (m_index * 8)] >> 16) & 0xffff);
}
u16 vertex_texture::get_exact_mipmap_count() const
@ -334,116 +344,116 @@ namespace rsx
u8 vertex_texture::unsigned_remap() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf);
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf);
}
u8 vertex_texture::zfunc() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 28) & 0xf);
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 28) & 0xf);
}
u8 vertex_texture::gamma() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 20) & 0xf);
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 20) & 0xf);
}
u8 vertex_texture::aniso_bias() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 4) & 0xf);
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 4) & 0xf);
}
u8 vertex_texture::signed_remap() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 24) & 0xf);
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 24) & 0xf);
}
bool vertex_texture::enabled() const
{
return location() <= 1 && ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1);
return location() <= 1 && ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1);
}
u16 vertex_texture::min_lod() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 19) & 0xfff);
}
u16 vertex_texture::max_lod() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff);
}
rsx::texture_max_anisotropy vertex_texture::max_aniso() const
{
return rsx::to_texture_max_anisotropy((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7);
return rsx::to_texture_max_anisotropy((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7);
}
bool vertex_texture::alpha_kill_enabled() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 2) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 2) & 0x1);
}
u16 vertex_texture::bias() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff);
}
rsx::texture_minify_filter vertex_texture::min_filter() const
{
return rsx::to_texture_minify_filter((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7);
return rsx::to_texture_minify_filter((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7);
}
rsx::texture_magnify_filter vertex_texture::mag_filter() const
{
return rsx::to_texture_magnify_filter((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7);
return rsx::to_texture_magnify_filter((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7);
}
u8 vertex_texture::convolution_filter() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf);
}
bool vertex_texture::a_signed() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1);
}
bool vertex_texture::r_signed() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 29) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 29) & 0x1);
}
bool vertex_texture::g_signed() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 30) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 30) & 0x1);
}
bool vertex_texture::b_signed() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 31) & 0x1);
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 31) & 0x1);
}
u16 vertex_texture::width() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)] >> 16) & 0xffff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)] >> 16) & 0xffff);
}
u16 vertex_texture::height() const
{
return ((method_registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)]) & 0xffff);
return ((registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)]) & 0xffff);
}
u32 vertex_texture::border_color() const
{
return method_registers[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 8)];
return registers[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 8)];
}
u16 vertex_texture::depth() const
{
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] >> 20;
return registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] >> 20;
}
u32 vertex_texture::pitch() const
{
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] & 0xfffff;
return registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] & 0xfffff;
}
}

View File

@ -18,8 +18,12 @@ namespace rsx
{
protected:
u8 m_index;
std::array<u32, 0x10000 / 4> &registers;
public:
texture(u8 idx, std::array<u32, 0x10000 / 4> &r);
texture() = delete;
//initialize texture registers with default values
void init(u8 index);
@ -90,8 +94,12 @@ namespace rsx
{
protected:
u8 m_index;
std::array<u32, 0x10000 / 4> &registers;
public:
vertex_texture(u8 idx, std::array<u32, 0x10000 / 4> &r);
vertex_texture() = delete;
//initialize texture registers with default values
void init(u8 index);

View File

@ -303,15 +303,13 @@ namespace rsx
{
frame_capture_data::draw_state draw_state = {};
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
draw_state.width = clip_w;
draw_state.height = clip_h;
draw_state.color_format = surface.color_format;
draw_state.color_format = rsx::method_registers.surface_color();
draw_state.color_buffer = std::move(copy_render_targets_to_memory());
draw_state.depth_format = surface.depth_format;
draw_state.depth_format = rsx::method_registers.surface_depth_fmt();
draw_state.depth_stencil = std::move(copy_depth_stencil_buffer_to_memory());
if (draw_command == rsx::draw_command::indexed)
@ -321,7 +319,7 @@ namespace rsx
{
draw_state.vertex_count += range.second;
}
draw_state.index_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
draw_state.index_type = rsx::method_registers.index_type();
if (draw_state.index_type == rsx::index_array_type::u16)
{
@ -346,17 +344,17 @@ namespace rsx
inline_vertex_array.clear();
first_count_commands.clear();
draw_command = rsx::draw_command::none;
draw_mode = to_primitive_type(method_registers[NV4097_SET_BEGIN_END]);
draw_mode = method_registers.primitive_mode();
}
void thread::end()
{
transform_constants.clear();
rsx::method_registers.transform_constants.clear();
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
register_vertex_info[index].size = 0;
register_vertex_data[index].clear();
rsx::method_registers.register_vertex_info[index].size = 0;
rsx::method_registers.register_vertex_data[index].clear();
}
if (capture_current_frame)
@ -494,21 +492,21 @@ namespace rsx
void thread::fill_scale_offset_data(void *buffer, bool is_d3d) const
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
float scale_x = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_SCALE] / (clip_w / 2.f);
float offset_x = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_OFFSET] - (clip_w / 2.f);
float scale_x = rsx::method_registers.viewport_scale_x() / (clip_w / 2.f);
float offset_x = rsx::method_registers.viewport_offset_x() - (clip_w / 2.f);
offset_x /= clip_w / 2.f;
float scale_y = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_SCALE + 1] / (clip_h / 2.f);
float offset_y = ((float&)rsx::method_registers[NV4097_SET_VIEWPORT_OFFSET + 1] - (clip_h / 2.f));
float scale_y = rsx::method_registers.viewport_scale_y() / (clip_h / 2.f);
float offset_y = (rsx::method_registers.viewport_offset_y() - (clip_h / 2.f));
offset_y /= clip_h / 2.f;
if (is_d3d) scale_y *= -1;
if (is_d3d) offset_y *= -1;
float scale_z = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_SCALE + 2];
float offset_z = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_OFFSET + 2];
float scale_z = rsx::method_registers.viewport_scale_z();
float offset_z = rsx::method_registers.viewport_offset_z();
if (!is_d3d) offset_z -= .5;
float one = 1.f;
@ -525,7 +523,7 @@ namespace rsx
*/
void thread::fill_vertex_program_constants_data(void *buffer)
{
for (const auto &entry : transform_constants)
for (const auto &entry : rsx::method_registers.transform_constants)
local_transform_constants[entry.first] = entry.second;
for (const auto &entry : local_transform_constants)
stream_vector_from_memory((char*)buffer + entry.first * 4 * sizeof(float), (void*)entry.second.rgba);
@ -541,7 +539,7 @@ namespace rsx
{
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
const auto &info = vertex_arrays_info[index];
const auto &info = rsx::method_registers.vertex_arrays_info[index];
if (!info.size) // disabled
continue;
@ -642,17 +640,17 @@ namespace rsx
{
u32 offset_color[] =
{
rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET]
rsx::method_registers.surface_a_offset(),
rsx::method_registers.surface_b_offset(),
rsx::method_registers.surface_c_offset(),
rsx::method_registers.surface_d_offset(),
};
u32 context_dma_color[] =
{
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D]
rsx::method_registers.surface_a_dma(),
rsx::method_registers.surface_b_dma(),
rsx::method_registers.surface_c_dma(),
rsx::method_registers.surface_d_dma(),
};
return
{
@ -665,32 +663,32 @@ namespace rsx
u32 thread::get_zeta_surface_address() const
{
u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET];
u32 m_context_dma_z = rsx::method_registers.surface_z_dma();
u32 offset_zeta = rsx::method_registers.surface_z_offset();
return rsx::get_address(offset_zeta, m_context_dma_z);
}
RSXVertexProgram thread::get_current_vertex_program() const
{
RSXVertexProgram result = {};
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
u32 transform_program_start = rsx::method_registers.transform_program_start();
result.data.reserve((512 - transform_program_start) * 4);
for (int i = transform_program_start; i < 512; ++i)
{
result.data.resize((i - transform_program_start) * 4 + 4);
memcpy(result.data.data() + (i - transform_program_start) * 4, transform_program + i * 4, 4 * sizeof(u32));
memcpy(result.data.data() + (i - transform_program_start) * 4, rsx::method_registers.transform_program.data() + i * 4, 4 * sizeof(u32));
D3 d3;
d3.HEX = transform_program[i * 4 + 3];
d3.HEX = rsx::method_registers.transform_program[i * 4 + 3];
if (d3.end)
break;
}
result.output_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK];
result.output_mask = rsx::method_registers.vertex_attrib_output_mask();
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
u32 modulo_mask = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION];
u32 input_mask = rsx::method_registers.vertex_attrib_input_mask();
u32 modulo_mask = rsx::method_registers.frequency_divider_operation_mask();
result.rsx_vertex_inputs.clear();
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
@ -698,29 +696,29 @@ namespace rsx
if (!enabled)
continue;
if (vertex_arrays_info[index].size > 0)
if (rsx::method_registers.vertex_arrays_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{
index,
vertex_arrays_info[index].size,
vertex_arrays_info[index].frequency,
rsx::method_registers.vertex_arrays_info[index].size,
rsx::method_registers.vertex_arrays_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
true,
is_int_type(vertex_arrays_info[index].type)
is_int_type(rsx::method_registers.vertex_arrays_info[index].type)
}
);
}
else if (register_vertex_info[index].size > 0)
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{
index,
register_vertex_info[index].size,
register_vertex_info[index].frequency,
rsx::method_registers.register_vertex_info[index].size,
rsx::method_registers.register_vertex_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
false,
is_int_type(vertex_arrays_info[index].type)
is_int_type(rsx::method_registers.vertex_arrays_info[index].type)
}
);
}
@ -732,29 +730,28 @@ namespace rsx
RSXFragmentProgram thread::get_current_fragment_program() const
{
RSXFragmentProgram result = {};
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
u32 shader_program = rsx::method_registers.shader_program_address();
result.offset = shader_program & ~0x3;
result.addr = vm::base(rsx::get_address(result.offset, (shader_program & 0x3) - 1));
result.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
result.ctrl = rsx::method_registers.shader_control();
result.unnormalized_coords = 0;
result.front_back_color_enabled = !rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN];
result.back_color_diffuse_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.alpha_func = to_comparaison_function(rsx::method_registers[NV4097_SET_ALPHA_FUNC]);
result.fog_equation = rsx::to_fog_mode(rsx::method_registers[NV4097_SET_FOG_MODE]);
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
result.origin_mode = rsx::to_window_origin((shader_window >> 12) & 0xF);
result.pixel_center_mode = rsx::to_window_pixel_center((shader_window >> 16) & 0xF);
result.height = shader_window & 0xFFF;
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
result.back_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.alpha_func = rsx::method_registers.alpha_func();
result.fog_equation = rsx::method_registers.fog_equation();
result.origin_mode = rsx::method_registers.shader_window_origin();
result.pixel_center_mode = rsx::method_registers.shader_window_pixel();
result.height = rsx::method_registers.shader_window_height();
std::array<texture_dimension_extended, 16> texture_dimensions;
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
{
if (!textures[i].enabled())
if (!rsx::method_registers.fragment_textures[i].enabled())
texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d;
else
texture_dimensions[i] = textures[i].get_extended_texture_dimension();
if (textures[i].enabled() && (textures[i].format() & CELL_GCM_TEXTURE_UN))
texture_dimensions[i] = rsx::method_registers.fragment_textures[i].get_extended_texture_dimension();
if (rsx::method_registers.fragment_textures[i].enabled() && (rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN))
result.unnormalized_coords |= (1 << i);
}
result.set_texture_dimension(texture_dimensions);
@ -766,29 +763,29 @@ namespace rsx
{
raw_program result{};
u32 fp_info = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
u32 fp_info = rsx::method_registers.shader_program_address();
result.state.input_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
result.state.output_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK];
result.state.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
result.state.divider_op = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION];
result.state.alpha_func = rsx::method_registers[NV4097_SET_ALPHA_FUNC];
result.state.fog_mode = (u32)rsx::to_fog_mode(rsx::method_registers[NV4097_SET_FOG_MODE]);
result.state.input_attributes = rsx::method_registers.vertex_attrib_input_mask();
result.state.output_attributes = rsx::method_registers.vertex_attrib_output_mask();
result.state.ctrl = rsx::method_registers.shader_control();
result.state.divider_op = rsx::method_registers.frequency_divider_operation_mask();
result.state.alpha_func = (u32)rsx::method_registers.alpha_func();
result.state.fog_mode = (u32)rsx::method_registers.fog_equation();
result.state.is_int = 0;
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
bool is_int = false;
if (vertex_arrays_info[index].size > 0)
if (rsx::method_registers.vertex_arrays_info[index].size > 0)
{
is_int = is_int_type(vertex_arrays_info[index].type);
result.state.frequency[index] = vertex_arrays_info[index].frequency;
is_int = is_int_type(rsx::method_registers.vertex_arrays_info[index].type);
result.state.frequency[index] = rsx::method_registers.vertex_arrays_info[index].frequency;
}
else if (register_vertex_info[index].size > 0)
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
is_int = is_int_type(register_vertex_info[index].type);
result.state.frequency[index] = register_vertex_info[index].frequency;
is_int = is_int_type(rsx::method_registers.register_vertex_info[index].type);
result.state.frequency[index] = rsx::method_registers.register_vertex_info[index].frequency;
}
else
{
@ -803,7 +800,7 @@ namespace rsx
for (u8 index = 0; index < rsx::limits::textures_count; ++index)
{
if (!textures[index].enabled())
if (!rsx::method_registers.fragment_textures[index].enabled())
{
result.state.textures_alpha_kill[index] = 0;
result.state.textures_zfunc[index] = 0;
@ -811,10 +808,10 @@ namespace rsx
continue;
}
result.state.textures_alpha_kill[index] = textures[index].alpha_kill_enabled() ? 1 : 0;
result.state.textures_zfunc[index] = textures[index].zfunc();
result.state.textures_alpha_kill[index] = rsx::method_registers.fragment_textures[index].alpha_kill_enabled() ? 1 : 0;
result.state.textures_zfunc[index] = rsx::method_registers.fragment_textures[index].zfunc();
switch (textures[index].get_extended_texture_dimension())
switch (rsx::method_registers.fragment_textures[index].get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: result.state.textures[index] = rsx::texture_target::_1; break;
case rsx::texture_dimension_extended::texture_dimension_2d: result.state.textures[index] = rsx::texture_target::_2; break;
@ -829,13 +826,13 @@ namespace rsx
for (u8 index = 0; index < rsx::limits::vertex_textures_count; ++index)
{
if (!textures[index].enabled())
if (!rsx::method_registers.fragment_textures[index].enabled())
{
result.state.vertex_textures[index] = rsx::texture_target::none;
continue;
}
switch (textures[index].get_extended_texture_dimension())
switch (rsx::method_registers.fragment_textures[index].get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: result.state.vertex_textures[index] = rsx::texture_target::_1; break;
case rsx::texture_dimension_extended::texture_dimension_2d: result.state.vertex_textures[index] = rsx::texture_target::_2; break;
@ -848,8 +845,8 @@ namespace rsx
}
}
result.vertex_shader.ucode_ptr = transform_program;
result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
result.vertex_shader.ucode_ptr = rsx::method_registers.transform_program.data();
result.vertex_shader.offset = rsx::method_registers.transform_program_start();
result.fragment_shader.ucode_ptr = vm::base(rsx::get_address(fp_info & ~0x3, (fp_info & 0x3) - 1));
result.fragment_shader.offset = 0;
@ -859,90 +856,7 @@ namespace rsx
void thread::reset()
{
//setup method registers
std::memset(method_registers, 0, sizeof(method_registers));
method_registers[NV4097_SET_COLOR_MASK] = CELL_GCM_COLOR_MASK_R | CELL_GCM_COLOR_MASK_G | CELL_GCM_COLOR_MASK_B | CELL_GCM_COLOR_MASK_A;
method_registers[NV4097_SET_SCISSOR_HORIZONTAL] = (4096 << 16) | 0;
method_registers[NV4097_SET_SCISSOR_VERTICAL] = (4096 << 16) | 0;
method_registers[NV4097_SET_ALPHA_FUNC] = CELL_GCM_ALWAYS;
method_registers[NV4097_SET_ALPHA_REF] = 0;
method_registers[NV4097_SET_BLEND_FUNC_SFACTOR] = (CELL_GCM_ONE << 16) | CELL_GCM_ONE;
method_registers[NV4097_SET_BLEND_FUNC_DFACTOR] = (CELL_GCM_ZERO << 16) | CELL_GCM_ZERO;
method_registers[NV4097_SET_BLEND_COLOR] = 0;
method_registers[NV4097_SET_BLEND_COLOR2] = 0;
method_registers[NV4097_SET_BLEND_EQUATION] = (CELL_GCM_FUNC_ADD << 16) | CELL_GCM_FUNC_ADD;
method_registers[NV4097_SET_STENCIL_MASK] = 0xff;
method_registers[NV4097_SET_STENCIL_FUNC] = CELL_GCM_ALWAYS;
method_registers[NV4097_SET_STENCIL_FUNC_REF] = 0x00;
method_registers[NV4097_SET_STENCIL_FUNC_MASK] = 0xff;
method_registers[NV4097_SET_STENCIL_OP_FAIL] = CELL_GCM_KEEP;
method_registers[NV4097_SET_STENCIL_OP_ZFAIL] = CELL_GCM_KEEP;
method_registers[NV4097_SET_STENCIL_OP_ZPASS] = CELL_GCM_KEEP;
method_registers[NV4097_SET_BACK_STENCIL_MASK] = 0xff;
method_registers[NV4097_SET_BACK_STENCIL_FUNC] = CELL_GCM_ALWAYS;
method_registers[NV4097_SET_BACK_STENCIL_FUNC_REF] = 0x00;
method_registers[NV4097_SET_BACK_STENCIL_FUNC_MASK] = 0xff;
method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL] = CELL_GCM_KEEP;
method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL] = CELL_GCM_KEEP;
method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS] = CELL_GCM_KEEP;
method_registers[NV4097_SET_SHADE_MODE] = CELL_GCM_SMOOTH;
method_registers[NV4097_SET_LOGIC_OP] = CELL_GCM_COPY;
(f32&)method_registers[NV4097_SET_DEPTH_BOUNDS_MIN] = 0.f;
(f32&)method_registers[NV4097_SET_DEPTH_BOUNDS_MAX] = 1.f;
(f32&)method_registers[NV4097_SET_CLIP_MIN] = 0.f;
(f32&)method_registers[NV4097_SET_CLIP_MAX] = 1.f;
method_registers[NV4097_SET_LINE_WIDTH] = 1 << 3;
// These defaults were found using After Burner Climax (which never set fog mode despite using fog input)
method_registers[NV4097_SET_FOG_MODE] = 0x2601; // rsx::fog_mode::linear;
(f32&)method_registers[NV4097_SET_FOG_PARAMS] = 1.;
(f32&)method_registers[NV4097_SET_FOG_PARAMS + 1] = 1.;
method_registers[NV4097_SET_DEPTH_FUNC] = CELL_GCM_LESS;
method_registers[NV4097_SET_DEPTH_MASK] = CELL_GCM_TRUE;
(f32&)method_registers[NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR] = 0.f;
(f32&)method_registers[NV4097_SET_POLYGON_OFFSET_BIAS] = 0.f;
method_registers[NV4097_SET_FRONT_POLYGON_MODE] = CELL_GCM_POLYGON_MODE_FILL;
method_registers[NV4097_SET_BACK_POLYGON_MODE] = CELL_GCM_POLYGON_MODE_FILL;
method_registers[NV4097_SET_CULL_FACE] = CELL_GCM_BACK;
method_registers[NV4097_SET_FRONT_FACE] = CELL_GCM_CCW;
method_registers[NV4097_SET_RESTART_INDEX] = -1;
method_registers[NV4097_SET_CLEAR_RECT_HORIZONTAL] = (4096 << 16) | 0;
method_registers[NV4097_SET_CLEAR_RECT_VERTICAL] = (4096 << 16) | 0;
method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] = 0xffffffff;
method_registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT;
rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN] = true;
rsx::method_registers[NV4097_SET_ALPHA_FUNC] = CELL_GCM_ALWAYS;
// Reset vertex attrib array
for (int i = 0; i < limits::vertex_count; i++)
{
vertex_arrays_info[i].size = 0;
}
// Construct Textures
for (int i = 0; i < limits::textures_count; i++)
{
textures[i].init(i);
}
for (int i = 0; i < limits::vertex_textures_count; i++)
{
vertex_textures[i].init(i);
}
rsx::method_registers.reset();
}
void thread::init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)

View File

@ -179,22 +179,6 @@ namespace rsx
}
};
struct data_array_format_info
{
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
vertex_base_type type = vertex_base_type::f;
void unpack_array(u32 data_array_format)
{
frequency = data_array_format >> 16;
stride = (data_array_format >> 8) & 0xff;
size = (data_array_format >> 4) & 0xf;
type = to_vertex_base_type(data_array_format & 0xf);
}
};
enum class draw_command
{
none,
@ -219,33 +203,8 @@ namespace rsx
GcmTileInfo tiles[limits::tiles_count];
GcmZcullInfo zculls[limits::zculls_count];
rsx::texture textures[limits::textures_count];
rsx::vertex_texture vertex_textures[limits::vertex_textures_count];
/**
* RSX can sources vertex attributes from 2 places:
* - Immediate values passed by NV4097_SET_VERTEX_DATA*_M + ARRAY_ID write.
* For a given ARRAY_ID the last command of this type defines the actual type of the immediate value.
* Since there can be only a single value per ARRAY_ID passed this way, all vertex in the draw call
* shares it.
* - Vertex array values passed by offset/stride/size/format description.
*
* A given ARRAY_ID can have both an immediate value and a vertex array enabled at the same time
* (See After Burner Climax intro cutscene). In such case the vertex array has precedence over the
* immediate value. As soon as the vertex array is disabled (size set to 0) the immediate value
* must be used if the vertex attrib mask request it.
*
* Note that behavior when both vertex array and immediate value system are disabled but vertex attrib mask
* request inputs is unknow.
*/
data_array_format_info register_vertex_info[limits::vertex_count];
std::vector<u8> register_vertex_data[limits::vertex_count];
data_array_format_info vertex_arrays_info[limits::vertex_count];
u32 vertex_draw_count = 0;
std::unordered_map<u32, color4_base<f32>> transform_constants;
/**
* Stores the first and count argument from draw/draw indexed parameters between begin/end clauses.
*/
@ -254,8 +213,6 @@ namespace rsx
// Constant stored for whole frame
std::unordered_map<u32, color4f> local_transform_constants;
u32 transform_program[512 * 4] = {};
bool capture_current_frame = false;
void capture_frame(const std::string &name);

View File

@ -12,9 +12,9 @@ namespace vk
gpu_formats_support get_optimal_tiling_supported_formats(VkPhysicalDevice physical_device);
VkFormat get_compatible_depth_surface_format(const gpu_formats_support &support, rsx::surface_depth_format format);
VkStencilOp get_stencil_op(u32 op);
VkLogicOp get_logic_op(u32 op);
VkFrontFace get_front_face_ccw(u32 ffv);
VkStencilOp get_stencil_op(rsx::stencil_op op);
VkLogicOp get_logic_op(rsx::logic_op op);
VkFrontFace get_front_face_ccw(rsx::front_face ffv);
VkCullModeFlags get_cull_face(u32 cfv);
VkBorderColor get_border_color(u8 color);

View File

@ -31,26 +31,26 @@ namespace
namespace vk
{
VkCompareOp compare_op(u32 gl_name)
VkCompareOp compare_op(rsx::comparaison_function op)
{
switch (gl_name)
switch (op)
{
case CELL_GCM_NEVER:
case rsx::comparaison_function::never:
return VK_COMPARE_OP_NEVER;
case CELL_GCM_GREATER:
case rsx::comparaison_function::greater:
return VK_COMPARE_OP_GREATER;
case CELL_GCM_LESS:
case rsx::comparaison_function::less:
return VK_COMPARE_OP_LESS;
case CELL_GCM_LEQUAL:
case rsx::comparaison_function::less_or_equal:
return VK_COMPARE_OP_LESS_OR_EQUAL;
case CELL_GCM_GEQUAL:
case rsx::comparaison_function::greater_or_equal:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
case CELL_GCM_EQUAL:
case rsx::comparaison_function::equal:
return VK_COMPARE_OP_EQUAL;
case CELL_GCM_ALWAYS:
case rsx::comparaison_function::always:
return VK_COMPARE_OP_ALWAYS;
default:
throw EXCEPTION("Unsupported compare op: 0x%X", gl_name);
throw EXCEPTION("Unsupported compare op: 0x%X", op);
}
}
@ -181,105 +181,106 @@ namespace vk
}
}
VkLogicOp get_logic_op(u32 op)
VkLogicOp get_logic_op(rsx::logic_op op)
{
switch (op)
{
case CELL_GCM_CLEAR: return VK_LOGIC_OP_CLEAR;
case CELL_GCM_AND: return VK_LOGIC_OP_AND;
case CELL_GCM_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;
case CELL_GCM_COPY: return VK_LOGIC_OP_COPY;
case CELL_GCM_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
case CELL_GCM_NOOP: return VK_LOGIC_OP_NO_OP;
case CELL_GCM_XOR: return VK_LOGIC_OP_XOR;
case CELL_GCM_OR: return VK_LOGIC_OP_OR;
case CELL_GCM_NOR: return VK_LOGIC_OP_NOR;
case CELL_GCM_EQUIV: return VK_LOGIC_OP_EQUIVALENT;
case CELL_GCM_INVERT: return VK_LOGIC_OP_INVERT;
case CELL_GCM_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
case CELL_GCM_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;
case CELL_GCM_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
case CELL_GCM_NAND: return VK_LOGIC_OP_NAND;
case rsx::logic_op::logic_clear: return VK_LOGIC_OP_CLEAR;
case rsx::logic_op::logic_and: return VK_LOGIC_OP_AND;
case rsx::logic_op::logic_and_reverse: return VK_LOGIC_OP_AND_REVERSE;
case rsx::logic_op::logic_copy: return VK_LOGIC_OP_COPY;
case rsx::logic_op::logic_and_inverted: return VK_LOGIC_OP_AND_INVERTED;
case rsx::logic_op::logic_noop: return VK_LOGIC_OP_NO_OP;
case rsx::logic_op::logic_xor: return VK_LOGIC_OP_XOR;
case rsx::logic_op::logic_or : return VK_LOGIC_OP_OR;
case rsx::logic_op::logic_nor: return VK_LOGIC_OP_NOR;
case rsx::logic_op::logic_equiv: return VK_LOGIC_OP_EQUIVALENT;
case rsx::logic_op::logic_invert: return VK_LOGIC_OP_INVERT;
case rsx::logic_op::logic_or_reverse: return VK_LOGIC_OP_OR_REVERSE;
case rsx::logic_op::logic_copy_inverted: return VK_LOGIC_OP_COPY_INVERTED;
case rsx::logic_op::logic_or_inverted: return VK_LOGIC_OP_OR_INVERTED;
case rsx::logic_op::logic_nand: return VK_LOGIC_OP_NAND;
default:
throw EXCEPTION("Unknown logic op 0x%X", op);
}
}
VkBlendFactor get_blend_factor(u16 factor)
VkBlendFactor get_blend_factor(rsx::blend_factor factor)
{
switch (factor)
{
case CELL_GCM_ONE: return VK_BLEND_FACTOR_ONE;
case CELL_GCM_ZERO: return VK_BLEND_FACTOR_ZERO;
case CELL_GCM_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
case CELL_GCM_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;
case CELL_GCM_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;
case CELL_GCM_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;
case CELL_GCM_CONSTANT_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR;
case CELL_GCM_CONSTANT_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
case CELL_GCM_ONE_MINUS_SRC_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
case CELL_GCM_ONE_MINUS_DST_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
case CELL_GCM_ONE_MINUS_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
case CELL_GCM_ONE_MINUS_DST_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
case CELL_GCM_ONE_MINUS_CONSTANT_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
case CELL_GCM_ONE_MINUS_CONSTANT_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
case rsx::blend_factor::one: return VK_BLEND_FACTOR_ONE;
case rsx::blend_factor::zero: return VK_BLEND_FACTOR_ZERO;
case rsx::blend_factor::src_alpha: return VK_BLEND_FACTOR_SRC_ALPHA;
case rsx::blend_factor::dst_alpha: return VK_BLEND_FACTOR_DST_ALPHA;
case rsx::blend_factor::src_color: return VK_BLEND_FACTOR_SRC_COLOR;
case rsx::blend_factor::dst_color: return VK_BLEND_FACTOR_DST_COLOR;
case rsx::blend_factor::constant_color: return VK_BLEND_FACTOR_CONSTANT_COLOR;
case rsx::blend_factor::constant_alpha: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
case rsx::blend_factor::one_minus_src_color: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
case rsx::blend_factor::one_minus_dst_color: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
case rsx::blend_factor::one_minus_src_alpha: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
case rsx::blend_factor::one_minus_dst_alpha: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
case rsx::blend_factor::one_minus_constant_alpha: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
case rsx::blend_factor::one_minus_constant_color: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
default:
throw EXCEPTION("Unknown blend factor 0x%X", factor);
}
};
VkBlendOp get_blend_op(u16 op)
VkBlendOp get_blend_op(rsx::blend_equation op)
{
switch (op)
{
case CELL_GCM_FUNC_ADD: return VK_BLEND_OP_ADD;
case CELL_GCM_FUNC_SUBTRACT: return VK_BLEND_OP_SUBTRACT;
case CELL_GCM_FUNC_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
case CELL_GCM_MIN: return VK_BLEND_OP_MIN;
case CELL_GCM_MAX: return VK_BLEND_OP_MAX;
case rsx::blend_equation::add: return VK_BLEND_OP_ADD;
case rsx::blend_equation::substract: return VK_BLEND_OP_SUBTRACT;
case rsx::blend_equation::reverse_substract: return VK_BLEND_OP_REVERSE_SUBTRACT;
case rsx::blend_equation::min: return VK_BLEND_OP_MIN;
case rsx::blend_equation::max: return VK_BLEND_OP_MAX;
default:
throw EXCEPTION("Unknown blend op: 0x%X", op);
}
}
VkStencilOp get_stencil_op(u32 op)
VkStencilOp get_stencil_op(rsx::stencil_op op)
{
switch (op)
{
case CELL_GCM_KEEP: return VK_STENCIL_OP_KEEP;
case CELL_GCM_ZERO: return VK_STENCIL_OP_ZERO;
case CELL_GCM_REPLACE: return VK_STENCIL_OP_REPLACE;
case CELL_GCM_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case CELL_GCM_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case CELL_GCM_INVERT: return VK_STENCIL_OP_INVERT;
case CELL_GCM_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case CELL_GCM_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
case rsx::stencil_op::keep: return VK_STENCIL_OP_KEEP;
case rsx::stencil_op::zero: return VK_STENCIL_OP_ZERO;
case rsx::stencil_op::replace: return VK_STENCIL_OP_REPLACE;
case rsx::stencil_op::incr: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case rsx::stencil_op::decr: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case rsx::stencil_op::invert: return VK_STENCIL_OP_INVERT;
case rsx::stencil_op::incr_wrap: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case rsx::stencil_op::decr_wrap: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
default:
throw EXCEPTION("Unknown stencil op: 0x%X", op);
}
}
VkFrontFace get_front_face_ccw(u32 ffv)
VkFrontFace get_front_face_ccw(rsx::front_face ffv)
{
switch (ffv)
{
default: // Disgaea 3 pass some garbage value at startup, this is needed to survive.
case CELL_GCM_CW: return VK_FRONT_FACE_CLOCKWISE;
case CELL_GCM_CCW: return VK_FRONT_FACE_COUNTER_CLOCKWISE;
case rsx::front_face::cw: return VK_FRONT_FACE_CLOCKWISE;
case rsx::front_face::ccw: return VK_FRONT_FACE_COUNTER_CLOCKWISE;
default:
throw EXCEPTION("Unknown front face value: 0x%X", ffv);
}
throw EXCEPTION("Unknown front face value: 0x%X", ffv);
}
VkCullModeFlags get_cull_face(u32 cfv)
{
switch (cfv)
{
case CELL_GCM_FRONT: return VK_CULL_MODE_FRONT_BIT;
case CELL_GCM_BACK: return VK_CULL_MODE_BACK_BIT;
case CELL_GCM_FRONT_AND_BACK: return VK_CULL_MODE_FRONT_AND_BACK;
default: return VK_CULL_MODE_NONE;
}
throw EXCEPTION("Unknown cull face value: 0x%X", cfv);
VkCullModeFlags get_cull_face(u32 cfv)
{
switch (cfv)
{
case CELL_GCM_FRONT: return VK_CULL_MODE_FRONT_BIT;
case CELL_GCM_BACK: return VK_CULL_MODE_BACK_BIT;
case CELL_GCM_FRONT_AND_BACK: return VK_CULL_MODE_FRONT_AND_BACK;
default: return VK_CULL_MODE_NONE;
}
throw EXCEPTION("Unknown cull face value: 0x%X", cfv);
}
}
@ -607,8 +608,7 @@ void VKGSRender::begin()
if (!load_program())
return;
u32 line_width = rsx::method_registers[NV4097_SET_LINE_WIDTH];
float actual_line_width = (line_width >> 3) + (line_width & 7) / 8.f;
float actual_line_width = rsx::method_registers.line_width();
vkCmdSetLineWidth(m_command_buffer, actual_line_width);
@ -639,35 +639,34 @@ namespace
}
void VKGSRender::end()
{
size_t idx = vk::get_render_pass_location(
vk::get_compatible_surface_format(m_surface.color_format).first,
vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, m_surface.depth_format),
(u8)vk::get_draw_buffers(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])).size());
vk::get_compatible_surface_format(rsx::method_registers.surface_color()).first,
vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, rsx::method_registers.surface_depth_fmt()),
(u8)vk::get_draw_buffers(rsx::method_registers.surface_color_target()).size());
VkRenderPass current_render_pass = m_render_passes[idx];
for (int i = 0; i < rsx::limits::textures_count; ++i)
{
if (m_program->has_uniform("tex" + std::to_string(i)))
{
if (!textures[i].enabled())
if (!rsx::method_registers.fragment_textures[i].enabled())
{
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets);
continue;
}
vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, rsx::method_registers.fragment_textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
VkFilter min_filter;
VkSamplerMipmapMode mip_mode;
std::tie(min_filter, mip_mode) = vk::get_min_filter_and_mip(textures[i].min_filter());
std::tie(min_filter, mip_mode) = vk::get_min_filter_and_mip(rsx::method_registers.fragment_textures[i].min_filter());
m_sampler_to_clean.push_back(std::make_unique<vk::sampler>(
*m_device,
vk::vk_wrap_mode(textures[i].wrap_s()), vk::vk_wrap_mode(textures[i].wrap_t()), vk::vk_wrap_mode(textures[i].wrap_r()),
!!(textures[i].format() & CELL_GCM_TEXTURE_UN),
textures[i].bias(), vk::max_aniso(textures[i].max_aniso()), textures[i].min_lod(), textures[i].max_lod(),
min_filter, vk::get_mag_filter(textures[i].mag_filter()), mip_mode, vk::get_border_color(textures[i].border_color())
vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_s()), vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_t()), vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_r()),
!!(rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN),
rsx::method_registers.fragment_textures[i].bias(), vk::max_aniso(rsx::method_registers.fragment_textures[i].max_aniso()), rsx::method_registers.fragment_textures[i].min_lod(), rsx::method_registers.fragment_textures[i].max_lod(),
min_filter, vk::get_mag_filter(rsx::method_registers.fragment_textures[i].mag_filter()), mip_mode, vk::get_border_color(rsx::method_registers.fragment_textures[i].border_color())
));
m_program->bind_uniform({ m_sampler_to_clean.back()->value, texture0->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets);
}
@ -710,23 +709,18 @@ void VKGSRender::end()
void VKGSRender::set_viewport()
{
u32 viewport_horizontal = rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL];
u32 viewport_vertical = rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL];
u16 viewport_x = rsx::method_registers.viewport_origin_x();
u16 viewport_y = rsx::method_registers.viewport_origin_y();
u16 viewport_w = rsx::method_registers.viewport_width();
u16 viewport_h = rsx::method_registers.viewport_height();
u16 viewport_x = viewport_horizontal & 0xffff;
u16 viewport_y = viewport_vertical & 0xffff;
u16 viewport_w = viewport_horizontal >> 16;
u16 viewport_h = viewport_vertical >> 16;
u16 scissor_x = rsx::method_registers.scissor_origin_x();
u16 scissor_w = rsx::method_registers.scissor_width();
u16 scissor_y = rsx::method_registers.scissor_origin_y();
u16 scissor_h = rsx::method_registers.scissor_height();
u32 scissor_horizontal = rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL];
u32 scissor_vertical = rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL];
u16 scissor_x = scissor_horizontal;
u16 scissor_w = scissor_horizontal >> 16;
u16 scissor_y = scissor_vertical;
u16 scissor_h = scissor_vertical >> 16;
// u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
// rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
// u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
// rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
VkViewport viewport = {};
viewport.x = viewport_x;
@ -763,8 +757,7 @@ void VKGSRender::clear_surface(u32 mask)
{
//TODO: Build clear commands into current renderpass descriptor set
if (!(mask & 0xF3)) return;
if (m_current_present_image== 0xFFFF) return;
if (!rsx::method_registers[NV4097_SET_SURFACE_FORMAT]) return;
if (m_current_present_image == 0xFFFF) return;
init_buffers();
@ -774,13 +767,13 @@ void VKGSRender::clear_surface(u32 mask)
VkClearValue depth_stencil_clear_values, color_clear_values;
VkImageSubresourceRange depth_range = vk::get_image_subresource_range(0, 0, 1, 1, 0);
rsx::surface_depth_format surface_depth_format = rsx::to_surface_depth_format((rsx::method_registers[NV4097_SET_SURFACE_FORMAT] >> 5) & 0x7);
rsx::surface_depth_format surface_depth_format = rsx::method_registers.surface_depth_fmt();
if (mask & 0x1)
{
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
u32 clear_depth = rsx::method_registers.z_clear_value();
float depth_clear = (float)clear_depth / max_depth_value;
depth_range.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
@ -790,8 +783,8 @@ void VKGSRender::clear_surface(u32 mask)
if (mask & 0x2)
{
u8 clear_stencil = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] & 0xff;
u32 stencil_mask = rsx::method_registers[NV4097_SET_STENCIL_MASK];
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
u32 stencil_mask = rsx::method_registers.stencil_mask();
//TODO set stencil mask
depth_range.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
@ -800,11 +793,10 @@ void VKGSRender::clear_surface(u32 mask)
if (mask & 0xF0)
{
u32 clear_color = rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE];
u8 clear_a = clear_color >> 24;
u8 clear_r = clear_color >> 16;
u8 clear_g = clear_color >> 8;
u8 clear_b = clear_color;
u8 clear_a = rsx::method_registers.clear_color_a();
u8 clear_r = rsx::method_registers.clear_color_r();
u8 clear_g = rsx::method_registers.clear_color_g();
u8 clear_b = rsx::method_registers.clear_color_b();
//TODO set color mask
/*VkBool32 clear_red = (VkBool32)!!(mask & 0x20);
@ -878,12 +870,12 @@ bool VKGSRender::load_program()
bool unused;
properties.ia.topology = vk::get_appropriate_topology(draw_mode, unused);
if (rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE])
if (rsx::method_registers.restart_index_enabled())
{
if (rsx::method_registers[NV4097_SET_RESTART_INDEX] != 0xFFFF &&
rsx::method_registers[NV4097_SET_RESTART_INDEX] != 0xFFFFFFFF)
if (rsx::method_registers.restart_index() != 0xFFFF &&
rsx::method_registers.restart_index() != 0xFFFFFFFF)
{
LOG_ERROR(RSX, "Custom primitive restart index 0x%X. Should rewrite index buffer with proper value!", rsx::method_registers[NV4097_SET_RESTART_INDEX]);
LOG_ERROR(RSX, "Custom primitive restart index 0x%X. Should rewrite index buffer with proper value!", rsx::method_registers.restart_index());
}
properties.ia.primitiveRestartEnable = VK_TRUE;
}
@ -897,17 +889,11 @@ bool VKGSRender::load_program()
properties.att_state[i].blendEnable = VK_FALSE;
}
u32 color_mask = rsx::method_registers[NV4097_SET_COLOR_MASK];
bool color_mask_b = !!(color_mask & 0xff);
bool color_mask_g = !!((color_mask >> 8) & 0xff);
bool color_mask_r = !!((color_mask >> 16) & 0xff);
bool color_mask_a = !!((color_mask >> 24) & 0xff);
VkColorComponentFlags mask = 0;
if (color_mask_a) mask |= VK_COLOR_COMPONENT_A_BIT;
if (color_mask_b) mask |= VK_COLOR_COMPONENT_B_BIT;
if (color_mask_g) mask |= VK_COLOR_COMPONENT_G_BIT;
if (color_mask_r) mask |= VK_COLOR_COMPONENT_R_BIT;
if (rsx::method_registers.color_mask_a()) mask |= VK_COLOR_COMPONENT_A_BIT;
if (rsx::method_registers.color_mask_b()) mask |= VK_COLOR_COMPONENT_B_BIT;
if (rsx::method_registers.color_mask_g()) mask |= VK_COLOR_COMPONENT_G_BIT;
if (rsx::method_registers.color_mask_r()) mask |= VK_COLOR_COMPONENT_R_BIT;
VkColorComponentFlags color_masks[4] = { mask };
@ -918,19 +904,15 @@ bool VKGSRender::load_program()
properties.att_state[render_targets[idx]].colorWriteMask = mask;
}
if (rsx::method_registers[NV4097_SET_BLEND_ENABLE])
if (rsx::method_registers.blend_enabled())
{
u32 sfactor = rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR];
u32 dfactor = rsx::method_registers[NV4097_SET_BLEND_FUNC_DFACTOR];
VkBlendFactor sfactor_rgb = vk::get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb());
VkBlendFactor sfactor_a = vk::get_blend_factor(rsx::method_registers.blend_func_sfactor_a());
VkBlendFactor dfactor_rgb = vk::get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb());
VkBlendFactor dfactor_a = vk::get_blend_factor(rsx::method_registers.blend_func_dfactor_a());
VkBlendFactor sfactor_rgb = vk::get_blend_factor(sfactor);
VkBlendFactor sfactor_a = vk::get_blend_factor(sfactor >> 16);
VkBlendFactor dfactor_rgb = vk::get_blend_factor(dfactor);
VkBlendFactor dfactor_a = vk::get_blend_factor(dfactor >> 16);
u32 equation = rsx::method_registers[NV4097_SET_BLEND_EQUATION];
VkBlendOp equation_rgb = vk::get_blend_op(equation);
VkBlendOp equation_a = vk::get_blend_op(equation >> 16);
VkBlendOp equation_rgb = vk::get_blend_op(rsx::method_registers.blend_equation_rgb());
VkBlendOp equation_a = vk::get_blend_op(rsx::method_registers.blend_equation_a());
//TODO: Separate target blending
for (u8 idx = 0; idx < m_draw_buffers_count; ++idx)
@ -952,67 +934,83 @@ bool VKGSRender::load_program()
}
}
if (rsx::method_registers[NV4097_SET_LOGIC_OP_ENABLE])
if (rsx::method_registers.logic_op_enabled())
{
properties.cs.logicOpEnable = true;
properties.cs.logicOp = vk::get_logic_op(rsx::method_registers[NV4097_SET_LOGIC_OP]);
properties.cs.logicOp = vk::get_logic_op(rsx::method_registers.logic_operation());
}
properties.ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
properties.ds.depthWriteEnable = (!!rsx::method_registers[NV4097_SET_DEPTH_MASK]) ? VK_TRUE : VK_FALSE;
properties.ds.depthWriteEnable = rsx::method_registers.depth_write_enabled() ? VK_TRUE : VK_FALSE;
if (rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE])
if (rsx::method_registers.depth_bounds_test_enabled())
{
properties.ds.depthBoundsTestEnable = VK_TRUE;
properties.ds.minDepthBounds = (f32&)rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_MIN];
properties.ds.maxDepthBounds = (f32&)rsx::method_registers[NV4097_SET_DEPTH_BOUNDS_MAX];
properties.ds.minDepthBounds = rsx::method_registers.depth_bounds_min();
properties.ds.maxDepthBounds = rsx::method_registers.depth_bounds_max();
}
else
properties.ds.depthBoundsTestEnable = VK_FALSE;
if (rsx::method_registers[NV4097_SET_STENCIL_TEST_ENABLE])
if (rsx::method_registers.stencil_test_enabled())
{
properties.ds.stencilTestEnable = VK_TRUE;
properties.ds.front.writeMask = rsx::method_registers[NV4097_SET_STENCIL_MASK];
properties.ds.front.compareMask = rsx::method_registers[NV4097_SET_STENCIL_FUNC_MASK];
properties.ds.front.reference = rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF];
properties.ds.front.failOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL]);
properties.ds.front.passOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]);
properties.ds.front.depthFailOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL]);
properties.ds.front.compareOp = vk::compare_op(rsx::method_registers[NV4097_SET_STENCIL_FUNC]);
properties.ds.front.writeMask = rsx::method_registers.stencil_mask();
properties.ds.front.compareMask = rsx::method_registers.stencil_func_mask();
properties.ds.front.reference = rsx::method_registers.stencil_func_ref();
properties.ds.front.failOp = vk::get_stencil_op(rsx::method_registers.stencil_op_fail());
properties.ds.front.passOp = vk::get_stencil_op(rsx::method_registers.stencil_op_zpass());
properties.ds.front.depthFailOp = vk::get_stencil_op(rsx::method_registers.stencil_op_zfail());
properties.ds.front.compareOp = vk::compare_op(rsx::method_registers.stencil_func());
if (rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE])
if (rsx::method_registers.two_sided_stencil_test_enabled())
{
properties.ds.back.failOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL]);
properties.ds.back.passOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS]);
properties.ds.back.depthFailOp = vk::get_stencil_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL]);
properties.ds.back.compareOp = vk::compare_op(rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC]);
properties.ds.back.failOp = vk::get_stencil_op(rsx::method_registers.back_stencil_op_fail());
properties.ds.back.passOp = vk::get_stencil_op(rsx::method_registers.back_stencil_op_zpass());
properties.ds.back.depthFailOp = vk::get_stencil_op(rsx::method_registers.back_stencil_op_zfail());
properties.ds.back.compareOp = vk::compare_op(rsx::method_registers.back_stencil_func());
}
else
properties.ds.back = properties.ds.front;
}
else
properties.ds.stencilTestEnable = VK_FALSE;
if (!!rsx::method_registers[NV4097_SET_DEPTH_TEST_ENABLE])
if (rsx::method_registers.depth_test_enabled())
{
properties.ds.depthTestEnable = VK_TRUE;
properties.ds.depthCompareOp = vk::compare_op(rsx::method_registers[NV4097_SET_DEPTH_FUNC]);
properties.ds.depthCompareOp = vk::compare_op(rsx::method_registers.depth_func());
}
else
properties.ds.depthTestEnable = VK_FALSE;
if (!!rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE])
{
properties.rs.cullMode = vk::get_cull_face(rsx::method_registers[NV4097_SET_CULL_FACE]);
if (rsx::method_registers.cull_face_enabled())
{
switch (rsx::method_registers.cull_face_mode())
{
case rsx::cull_face::front:
properties.rs.cullMode = VK_CULL_MODE_FRONT_BIT;
break;
case rsx::cull_face::back:
properties.rs.cullMode = VK_CULL_MODE_BACK_BIT;
break;
case rsx::cull_face::front_and_back:
properties.rs.cullMode = VK_CULL_MODE_FRONT_AND_BACK;
break;
default:
properties.rs.cullMode = VK_CULL_MODE_NONE;
break;
}
}
properties.rs.frontFace = vk::get_front_face_ccw(rsx::method_registers[NV4097_SET_FRONT_FACE]);
else
properties.rs.cullMode = VK_CULL_MODE_NONE;
properties.rs.frontFace = vk::get_front_face_ccw(rsx::method_registers.front_face_mode());
size_t idx = vk::get_render_pass_location(
vk::get_compatible_surface_format(m_surface.color_format).first,
vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, m_surface.depth_format),
(u8)vk::get_draw_buffers(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])).size());
vk::get_compatible_surface_format(rsx::method_registers.surface_color()).first,
vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, rsx::method_registers.surface_depth_fmt()),
(u8)vk::get_draw_buffers(rsx::method_registers.surface_color_target()).size());
properties.render_pass = m_render_passes[idx];
properties.num_targets = m_draw_buffers_count;
@ -1030,23 +1028,23 @@ bool VKGSRender::load_program()
//TODO: Add case for this in RSXThread
/**
* NOTE: While VK's coord system resembles GLs, the clip volume is no longer symetrical in z
* Its like D3D without the flip in y (depending on how you build the spir-v)
*/
* NOTE: While VK's coord system resembles GLs, the clip volume is no longer symetrical in z
* Its like D3D without the flip in y (depending on how you build the spir-v)
*/
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
float scale_x = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_SCALE] / (clip_w / 2.f);
float offset_x = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_OFFSET] - (clip_w / 2.f);
float scale_x = rsx::method_registers.viewport_scale_x() / (clip_w / 2.f);
float offset_x = rsx::method_registers.viewport_offset_x() - (clip_w / 2.f);
offset_x /= clip_w / 2.f;
float scale_y = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_SCALE + 1] / (clip_h / 2.f);
float offset_y = ((float&)rsx::method_registers[NV4097_SET_VIEWPORT_OFFSET + 1] - (clip_h / 2.f));
float scale_y = rsx::method_registers.viewport_scale_y() / (clip_h / 2.f);
float offset_y = (rsx::method_registers.viewport_offset_y() - (clip_h / 2.f));
offset_y /= clip_h / 2.f;
float scale_z = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_SCALE + 2];
float offset_z = (float&)rsx::method_registers[NV4097_SET_VIEWPORT_OFFSET + 2];
float scale_z = rsx::method_registers.viewport_scale_z();
float offset_z = rsx::method_registers.viewport_offset_z();
float one = 1.f;
@ -1056,12 +1054,14 @@ bool VKGSRender::load_program()
stream_vector((char*)buf + 48, 0, 0, 0, (u32&)one);
}
u32 is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]);
u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF);
u32 is_alpha_tested = rsx::method_registers.alpha_test_enabled();
u8 alpha_ref_raw = rsx::method_registers.alpha_ref();
float alpha_ref = alpha_ref_raw / 255.f;
memcpy((char*)buf + 64, &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float));
memcpy((char*)buf + 68, &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float));
f32 fog0 = rsx::method_registers.fog_params_0();
f32 fog1 = rsx::method_registers.fog_params_1();
memcpy((char*)buf + 64, &fog0, sizeof(float));
memcpy((char*)buf + 68, &fog1, sizeof(float));
memcpy((char*)buf + 72, &is_alpha_tested, sizeof(u32));
memcpy((char*)buf + 76, &alpha_ref, sizeof(float));
m_uniform_buffer_ring_info.unmap();
@ -1161,37 +1161,29 @@ void VKGSRender::open_command_buffer()
void VKGSRender::prepare_rtts()
{
u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT];
if (!m_rtts_dirty)
return;
m_rtts_dirty = false;
if (m_surface.format != surface_format)
m_surface.unpack(surface_format);
u32 clip_horizontal = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
u32 clip_vertical = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
u32 clip_width = clip_horizontal >> 16;
u32 clip_height = clip_vertical >> 16;
u32 clip_x = clip_horizontal;
u32 clip_y = clip_vertical;
u32 clip_width = rsx::method_registers.surface_clip_width();
u32 clip_height = rsx::method_registers.surface_clip_height();
u32 clip_x = rsx::method_registers.surface_clip_origin_x();
u32 clip_y = rsx::method_registers.surface_clip_origin_y();
m_rtts.prepare_render_target(&m_command_buffer,
surface_format,
clip_horizontal, clip_vertical,
rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]),
rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(),
rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height(),
rsx::method_registers.surface_color_target(),
get_color_surface_addresses(), get_zeta_surface_address(),
(*m_device), &m_command_buffer, m_optimal_tiling_supported_formats, m_memory_type_mapping);
//Bind created rtts as current fbo...
std::vector<u8> draw_buffers = vk::get_draw_buffers(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]));
std::vector<u8> draw_buffers = vk::get_draw_buffers(rsx::method_registers.surface_color_target());
std::vector<std::unique_ptr<vk::image_view>> fbo_images;
for (u8 index: draw_buffers)
for (u8 index : draw_buffers)
{
vk::image *raw = std::get<1>(m_rtts.m_bound_render_targets[index]);
@ -1212,7 +1204,7 @@ void VKGSRender::prepare_rtts()
vk::image *raw = (std::get<1>(m_rtts.m_bound_depth_stencil));
VkImageSubresourceRange subres = {};
subres.aspectMask = (m_surface.depth_format == rsx::surface_depth_format::z24s8) ? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) : VK_IMAGE_ASPECT_DEPTH_BIT;
subres.aspectMask = (rsx::method_registers.surface_depth_fmt() == rsx::surface_depth_format::z24s8) ? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) : VK_IMAGE_ASPECT_DEPTH_BIT;
subres.baseArrayLayer = 0;
subres.baseMipLevel = 0;
subres.layerCount = 1;
@ -1221,7 +1213,7 @@ void VKGSRender::prepare_rtts()
fbo_images.push_back(std::make_unique<vk::image_view>(*m_device, raw->value, VK_IMAGE_VIEW_TYPE_2D, raw->info.format, vk::default_component_map(), subres));
}
size_t idx = vk::get_render_pass_location(vk::get_compatible_surface_format(m_surface.color_format).first, vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, m_surface.depth_format), (u8)draw_buffers.size());
size_t idx = vk::get_render_pass_location(vk::get_compatible_surface_format(rsx::method_registers.surface_color()).first, vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, rsx::method_registers.surface_depth_fmt()), (u8)draw_buffers.size());
VkRenderPass current_render_pass = m_render_passes[idx];
m_framebuffer_to_clean.push_back(std::make_unique<vk::framebuffer>(*m_device, current_render_pass, clip_width, clip_height, std::move(fbo_images)));

View File

@ -21,8 +21,6 @@ private:
vk::glsl::program *m_program;
vk::context m_thread_context;
rsx::surface_info m_surface;
vk::vk_data_heap m_attrib_ring_info;
vk::texture_cache m_texture_cache;

View File

@ -301,7 +301,7 @@ VKGSRender::upload_vertex_data()
"in_tc4_buffer", "in_tc5_buffer", "in_tc6_buffer", "in_tc7_buffer"
};
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
u32 input_mask = rsx::method_registers.vertex_attrib_input_mask();
size_t offset_in_index_buffer = -1;
vertex_draw_count = 0;
@ -324,7 +324,7 @@ VKGSRender::upload_vertex_data()
if (draw_command == rsx::draw_command::indexed || primitives_emulated)
{
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
rsx::index_array_type type = rsx::method_registers.index_type();
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
if (is_indexed_draw) //Could be emulated or not, emulated array vertex count already computed above
@ -368,7 +368,7 @@ VKGSRender::upload_vertex_data()
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
const auto &info = vertex_arrays_info[i];
const auto &info = rsx::method_registers.vertex_arrays_info[i];
if (!info.size) continue;
offsets[i] = stride;
@ -379,7 +379,7 @@ VKGSRender::upload_vertex_data()
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
auto &vertex_info = vertex_arrays_info[index];
auto &vertex_info = rsx::method_registers.vertex_arrays_info[index];
if (!m_program->has_uniform(reg_table[index]))
continue;
@ -448,9 +448,9 @@ VKGSRender::upload_vertex_data()
continue;
}
if (vertex_arrays_info[index].size > 0)
if (rsx::method_registers.vertex_arrays_info[index].size > 0)
{
auto &vertex_info = vertex_arrays_info[index];
auto &vertex_info = rsx::method_registers.vertex_arrays_info[index];
// Fill vertex_array
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
@ -461,8 +461,8 @@ VKGSRender::upload_vertex_data()
bool requires_expansion = vk::requires_component_expansion(vertex_info.type, vertex_info.size);
// Get source pointer
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 base_offset = rsx::method_registers.vertex_data_base_offset();
u32 offset = rsx::method_registers.vertex_arrays_info[index].offset();
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address));
@ -505,11 +505,11 @@ VKGSRender::upload_vertex_data()
m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, upload_size));
m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets);
}
else if (register_vertex_info[index].size > 0)
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
//Untested!
auto &vertex_data = register_vertex_data[index];
auto &vertex_info = register_vertex_info[index];
auto &vertex_data = rsx::method_registers.register_vertex_data[index];
auto &vertex_info = rsx::method_registers.register_vertex_info[index];
switch (vertex_info.type)
{

View File

@ -8,6 +8,7 @@
#include "Emu/Cell/PPUCallback.h"
#include <thread>
#include <cassert>
cfg::map_entry<double> g_cfg_rsx_frame_limit(cfg::root.video, "Frame limit",
{
@ -21,7 +22,7 @@ cfg::map_entry<double> g_cfg_rsx_frame_limit(cfg::root.video, "Frame limit",
namespace rsx
{
u32 method_registers[0x10000 >> 2];
rsx_state method_registers;
rsx_method_t methods[0x10000 >> 2]{};
template<typename Type> struct vertex_data_type_from_element_type;
@ -40,7 +41,7 @@ namespace rsx
force_inline void semaphore_acquire(thread* rsx, u32 arg)
{
//TODO: dma
while (vm::ps3::read32(rsx->label_addr + method_registers[NV406E_SEMAPHORE_OFFSET]) != arg)
while (vm::ps3::read32(rsx->label_addr + method_registers.semaphore_offset_406e()) != arg)
{
if (Emu.IsStopped())
break;
@ -52,7 +53,7 @@ namespace rsx
force_inline void semaphore_release(thread* rsx, u32 arg)
{
//TODO: dma
vm::ps3::write32(rsx->label_addr + method_registers[NV406E_SEMAPHORE_OFFSET], arg);
vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_406e(), arg);
}
}
@ -61,13 +62,13 @@ namespace rsx
force_inline void texture_read_semaphore_release(thread* rsx, u32 arg)
{
//TODO: dma
vm::ps3::write32(rsx->label_addr + method_registers[NV4097_SET_SEMAPHORE_OFFSET], arg);
vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), arg);
}
force_inline void back_end_write_semaphore_release(thread* rsx, u32 arg)
{
//TODO: dma
vm::ps3::write32(rsx->label_addr + method_registers[NV4097_SET_SEMAPHORE_OFFSET],
vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(),
(arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff));
}
@ -78,14 +79,14 @@ namespace rsx
static const size_t element_size = (count * sizeof(type));
static const size_t element_size_in_words = element_size / sizeof(u32);
auto& info = rsx->register_vertex_info[index];
auto& info = rsx::method_registers.register_vertex_info[index];
info.type = vertex_data_type_from_element_type<type>::type;
info.size = count;
info.frequency = 0;
info.stride = 0;
auto& entry = rsx->register_vertex_data[index];
auto& entry = rsx::method_registers.register_vertex_data[index];
//find begin of data
size_t begin = id + index * element_size_in_words;
@ -93,7 +94,7 @@ namespace rsx
size_t position = entry.size();
entry.resize(position + element_size);
memcpy(entry.data() + position, method_registers + begin, element_size);
memcpy(entry.data() + position, &method_registers[begin], element_size);
}
template<u32 index>
@ -164,7 +165,7 @@ namespace rsx
{
force_inline static void impl(thread* rsx, u32 arg)
{
auto& info = rsx->vertex_arrays_info[index];
auto& info = rsx::method_registers.vertex_arrays_info[index];
info.unpack_array(arg);
}
};
@ -199,15 +200,7 @@ namespace rsx
{
force_inline static void impl(thread* rsxthr, u32 arg)
{
u32 load = method_registers[NV4097_SET_TRANSFORM_CONSTANT_LOAD];
static const size_t count = 4;
static const size_t size = count * sizeof(f32);
size_t reg = index / 4;
size_t subreg = index % 4;
memcpy(rsxthr->transform_constants[load + reg].rgba + subreg, method_registers + NV4097_SET_TRANSFORM_CONSTANT + reg * count + subreg, sizeof(f32));
method_registers.set_transform_constant(index, arg);
rsxthr->m_transform_constants_dirty = true;
}
};
@ -217,12 +210,7 @@ namespace rsx
{
force_inline static void impl(thread* rsx, u32 arg)
{
u32& load = method_registers[NV4097_SET_TRANSFORM_PROGRAM_LOAD];
static const size_t count = 4;
static const size_t size = count * sizeof(u32);
memcpy(rsx->transform_program + load++ * count, method_registers + NV4097_SET_TRANSFORM_PROGRAM + index * count, size);
method_registers.commit_4_transform_program_instructions(index);
}
};
@ -238,17 +226,16 @@ namespace rsx
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
auto &vertex_info = rsxthr->register_vertex_info[index];
auto &vertex_info = rsx::method_registers.register_vertex_info[index];
if (vertex_info.size > 0)
{
auto &vertex_data = rsxthr->register_vertex_data[index];
auto &vertex_data = rsx::method_registers.register_vertex_data[index];
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
u32 element_count = vertex_data.size() / element_size;
vertex_info.frequency = element_count;
rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION] |= 1 << index;
if (rsxthr->draw_command == rsx::draw_command::none)
{
@ -273,13 +260,13 @@ namespace rsx
{
u8 type = arg >> 24;
u32 offset = arg & 0xffffff;
u32 report_dma = method_registers[NV4097_SET_CONTEXT_DMA_REPORT];
blit_engine::context_dma report_dma = method_registers.context_dma_report();
u32 location;
switch (report_dma)
{
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT: location = CELL_GCM_LOCATION_LOCAL; break;
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: location = CELL_GCM_LOCATION_MAIN; break;
case blit_engine::context_dma::to_memory_get_report: location = CELL_GCM_LOCATION_LOCAL; break;
case blit_engine::context_dma::report_location_main: location = CELL_GCM_LOCATION_MAIN; break;
default:
LOG_WARNING(RSX, "nv4097::get_report: bad report dma: 0x%x", report_dma);
return;
@ -347,16 +334,15 @@ namespace rsx
{
force_inline static void impl(u32 arg)
{
u32 point = method_registers[NV308A_POINT];
u16 x = point;
u16 y = point >> 16;
u16 x = method_registers.nv308a_x();
u16 y = method_registers.nv308a_y();
if (y)
{
LOG_ERROR(RSX, "%s: y is not null (0x%x)", __FUNCTION__, y);
}
u32 address = get_address(method_registers[NV3062_SET_OFFSET_DESTIN] + (x << 2) + index * 4, method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN]);
u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + (x << 2) + index * 4, method_registers.blit_engine_output_location_nv3062());
vm::ps3::write32(address, arg);
}
};
@ -366,70 +352,65 @@ namespace rsx
{
never_inline void image_in(thread *rsx, u32 arg)
{
u32 operation = method_registers[NV3089_SET_OPERATION];
rsx::blit_engine::transfer_operation operation = method_registers.blit_engine_operation();
u32 clip_x = method_registers[NV3089_CLIP_POINT] & 0xffff;
u32 clip_y = method_registers[NV3089_CLIP_POINT] >> 16;
u32 clip_w = method_registers[NV3089_CLIP_SIZE] & 0xffff;
u32 clip_h = method_registers[NV3089_CLIP_SIZE] >> 16;
u32 clip_x = method_registers.blit_engine_clip_x();
u32 clip_y = method_registers.blit_engine_clip_y();
u32 clip_w = method_registers.blit_engine_clip_width();
u32 clip_h = method_registers.blit_engine_clip_height();
u32 out_x = method_registers[NV3089_IMAGE_OUT_POINT] & 0xffff;
u32 out_y = method_registers[NV3089_IMAGE_OUT_POINT] >> 16;
u32 out_w = method_registers[NV3089_IMAGE_OUT_SIZE] & 0xffff;
u32 out_h = method_registers[NV3089_IMAGE_OUT_SIZE] >> 16;
u32 out_x = method_registers.blit_engine_output_x();
u32 out_y = method_registers.blit_engine_output_y();
u32 out_w = method_registers.blit_engine_clip_width();
u32 out_h = method_registers.blit_engine_output_height();
u16 in_w = method_registers[NV3089_IMAGE_IN_SIZE];
u16 in_h = method_registers[NV3089_IMAGE_IN_SIZE] >> 16;
u16 in_pitch = method_registers[NV3089_IMAGE_IN_FORMAT];
u8 in_origin = method_registers[NV3089_IMAGE_IN_FORMAT] >> 16;
u8 in_inter = method_registers[NV3089_IMAGE_IN_FORMAT] >> 24;
u32 src_color_format = method_registers[NV3089_SET_COLOR_FORMAT];
u16 in_w = method_registers.blit_engine_input_width();
u16 in_h = method_registers.blit_engine_output_height();
u16 in_pitch = method_registers.blit_engine_input_pitch();
blit_engine::transfer_origin in_origin = method_registers.blit_engine_input_origin();
blit_engine::transfer_interpolator in_inter = method_registers.blit_engine_input_inter();
rsx::blit_engine::transfer_source_format src_color_format = method_registers.blit_engine_src_color_format();
f32 in_x = (method_registers[NV3089_IMAGE_IN] & 0xffff) / 16.f;
f32 in_y = (method_registers[NV3089_IMAGE_IN] >> 16) / 16.f;
f32 in_x = method_registers.blit_engine_in_x();
f32 in_y = method_registers.blit_engine_in_y();
if (in_origin != CELL_GCM_TRANSFER_ORIGIN_CORNER)
if (in_origin != blit_engine::transfer_origin::corner)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown origin (%d)", in_origin);
}
if (in_inter != CELL_GCM_TRANSFER_INTERPOLATOR_ZOH && in_inter != CELL_GCM_TRANSFER_INTERPOLATOR_FOH)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown inter (%d)", in_inter);
}
if (operation != CELL_GCM_TRANSFER_OPERATION_SRCCOPY)
if (operation != rsx::blit_engine::transfer_operation::srccopy)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown operation (%d)", operation);
}
const u32 src_offset = method_registers[NV3089_IMAGE_IN_OFFSET];
const u32 src_dma = method_registers[NV3089_SET_CONTEXT_DMA_IMAGE];
const u32 src_offset = method_registers.blit_engine_input_offset();
const u32 src_dma = method_registers.blit_engine_input_location();
u32 dst_offset;
u32 dst_dma = 0;
u16 dst_color_format;
rsx::blit_engine::transfer_destination_format dst_color_format;
u32 out_pitch = 0;
u32 out_aligment = 64;
switch (method_registers[NV3089_SET_CONTEXT_SURFACE])
switch (method_registers.blit_engine_context_surface())
{
case CELL_GCM_CONTEXT_SURFACE2D:
dst_dma = method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN];
dst_offset = method_registers[NV3062_SET_OFFSET_DESTIN];
dst_color_format = method_registers[NV3062_SET_COLOR_FORMAT];
out_pitch = method_registers[NV3062_SET_PITCH] >> 16;
out_aligment = method_registers[NV3062_SET_PITCH] & 0xffff;
case blit_engine::context_surface::surface2d:
dst_dma = method_registers.blit_engine_output_location_nv3062();
dst_offset = method_registers.blit_engine_output_offset_nv3062();
dst_color_format = method_registers.blit_engine_nv3062_color_format();
out_pitch = method_registers.blit_engine_output_pitch_nv3062();
out_aligment = method_registers.blit_engine_output_alignment_nv3062();
break;
case CELL_GCM_CONTEXT_SWIZZLE2D:
dst_dma = method_registers[NV309E_SET_CONTEXT_DMA_IMAGE];
dst_offset = method_registers[NV309E_SET_OFFSET];
dst_color_format = method_registers[NV309E_SET_FORMAT];
case blit_engine::context_surface::swizzle2d:
dst_dma = method_registers.blit_engine_nv309E_location();
dst_offset = method_registers.blit_engine_nv309E_offset();
dst_color_format = method_registers.blit_engine_output_format_nv309E();
break;
default:
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown m_context_surface (0x%x)", method_registers[NV3089_SET_CONTEXT_SURFACE]);
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown m_context_surface (0x%x)", method_registers.blit_engine_context_surface());
return;
}
@ -464,8 +445,8 @@ namespace rsx
}
}
u32 in_bpp = src_color_format == CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 ? 2 : 4; // bytes per pixel
u32 out_bpp = dst_color_format == CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 ? 2 : 4;
u32 in_bpp = (src_color_format == rsx::blit_engine::transfer_source_format::r5g6b5) ? 2 : 4; // bytes per pixel
u32 out_bpp = (dst_color_format == rsx::blit_engine::transfer_destination_format::r5g6b5) ? 2 : 4;
u32 in_offset = u32(in_x * in_bpp + in_pitch * in_y);
u32 out_offset = out_x * out_bpp + out_pitch * out_y;
@ -498,14 +479,14 @@ namespace rsx
u8* pixels_src = src_region.tile ? src_region.ptr + src_region.base : src_region.ptr;
u8* pixels_dst = vm::ps3::_ptr<u8>(dst_address + out_offset);
if (dst_color_format != CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 &&
dst_color_format != CELL_GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8)
if (dst_color_format != rsx::blit_engine::transfer_destination_format::r5g6b5 &&
dst_color_format != rsx::blit_engine::transfer_destination_format::a8r8g8b8)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown dst_color_format (%d)", dst_color_format);
}
if (src_color_format != CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 &&
src_color_format != CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8)
if (src_color_format != rsx::blit_engine::transfer_source_format::r5g6b5 &&
src_color_format != rsx::blit_engine::transfer_source_format::a8r8g8b8)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown src_color_format (%d)", src_color_format);
}
@ -516,18 +497,21 @@ namespace rsx
std::unique_ptr<u8[]> temp1, temp2, sw_temp;
AVPixelFormat in_format = src_color_format == CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB;
AVPixelFormat out_format = dst_color_format == CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB;
AVPixelFormat in_format = (src_color_format == rsx::blit_engine::transfer_source_format::r5g6b5) ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB;
AVPixelFormat out_format = (dst_color_format == rsx::blit_engine::transfer_destination_format::r5g6b5) ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB;
f32 scale_x = 1048576.f / method_registers[NV3089_DS_DX];
f32 scale_y = 1048576.f / method_registers[NV3089_DT_DY];
f32 scale_x = 1048576.f / method_registers.blit_engine_ds_dx();
f32 scale_y = 1048576.f / method_registers.blit_engine_dt_dy();
u32 convert_w = (u32)(scale_x * in_w);
u32 convert_h = (u32)(scale_y * in_h);
bool need_clip =
method_registers[NV3089_CLIP_SIZE] != method_registers[NV3089_IMAGE_IN_SIZE] ||
method_registers[NV3089_CLIP_POINT] || convert_w != out_w || convert_h != out_h;
method_registers.blit_engine_clip_width() != method_registers.blit_engine_input_width() ||
method_registers.blit_engine_clip_height() != method_registers.blit_engine_input_height() ||
method_registers.blit_engine_clip_x() > 0 ||
method_registers.blit_engine_clip_y() > 0 ||
convert_w != out_w || convert_h != out_h;
bool need_convert = out_format != in_format || scale_x != 1.0 || scale_y != 1.0;
@ -549,7 +533,7 @@ namespace rsx
}
}
if (method_registers[NV3089_SET_CONTEXT_SURFACE] != CELL_GCM_CONTEXT_SWIZZLE2D)
if (method_registers.blit_engine_context_surface() != blit_engine::context_surface::swizzle2d)
{
if (need_convert || need_clip)
{
@ -558,7 +542,7 @@ namespace rsx
if (need_convert)
{
convert_scale_image(temp1, out_format, convert_w, convert_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter ? true : false);
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);
clip_image(pixels_dst + out_offset, temp1.get(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
}
@ -570,7 +554,7 @@ namespace rsx
else
{
convert_scale_image(pixels_dst + out_offset, out_format, out_w, out_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter ? true : false);
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);
}
}
else
@ -600,7 +584,7 @@ namespace rsx
if (need_convert)
{
convert_scale_image(temp1, out_format, convert_w, convert_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter ? true : false);
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);
clip_image(temp2, temp1.get(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
}
@ -612,14 +596,14 @@ namespace rsx
else
{
convert_scale_image(temp2, out_format, out_w, out_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, clip_h, in_inter ? true : false);
pixels_src, in_format, in_w, in_h, in_pitch, clip_h, in_inter == blit_engine::transfer_interpolator::foh);
}
pixels_src = temp2.get();
}
u8 sw_width_log2 = method_registers[NV309E_SET_FORMAT] >> 16;
u8 sw_height_log2 = method_registers[NV309E_SET_FORMAT] >> 24;
u8 sw_width_log2 = method_registers.nv309e_sw_width_log2();
u8 sw_height_log2 = method_registers.nv309e_sw_height_log2();
// 0 indicates height of 1 pixel
sw_height_log2 = sw_height_log2 == 0 ? 1 : sw_height_log2;
@ -676,12 +660,12 @@ namespace rsx
{
force_inline void buffer_notify(u32 arg)
{
u32 in_pitch = method_registers[NV0039_PITCH_IN];
u32 out_pitch = method_registers[NV0039_PITCH_OUT];
const u32 line_length = method_registers[NV0039_LINE_LENGTH_IN];
const u32 line_count = method_registers[NV0039_LINE_COUNT];
const u8 out_format = method_registers[NV0039_FORMAT] >> 8;
const u8 in_format = method_registers[NV0039_FORMAT];
u32 in_pitch = method_registers.nv0039_input_pitch();
u32 out_pitch = method_registers.nv0039_output_pitch();
const u32 line_length = method_registers.nv0039_line_length();
const u32 line_count = method_registers.nv0039_line_count();
const u8 out_format = method_registers.nv0039_output_format();
const u8 in_format = method_registers.nv0039_input_format();
const u32 notify = arg;
// The existing GCM commands use only the value 0x1 for inFormat and outFormat
@ -700,11 +684,11 @@ namespace rsx
out_pitch = line_length;
}
u32 src_offset = method_registers[NV0039_OFFSET_IN];
u32 src_dma = method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_IN];
u32 src_offset = method_registers.nv0039_input_offset();
u32 src_dma = method_registers.nv0039_input_location();
u32 dst_offset = method_registers[NV0039_OFFSET_OUT];
u32 dst_dma = method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_OUT];
u32 dst_offset = method_registers.nv0039_output_offset();
u32 dst_dma = method_registers.nv0039_output_location();
u8 *dst = (u8*)vm::base(get_address(dst_offset, dst_dma));
const u8 *src = (u8*)vm::base(get_address(src_offset, src_dma));

File diff suppressed because it is too large Load Diff

View File

@ -70,14 +70,12 @@ namespace rsx
void fill_window_matrix(void *dest, bool transpose)
{
u32 shader_window = method_registers[NV4097_SET_SHADER_WINDOW];
u16 height = method_registers.shader_window_height();
window_origin origin = method_registers.shader_window_origin();
window_pixel_center pixelCenter = method_registers.shader_window_pixel();
u16 height = shader_window & 0xfff;
window_origin origin = to_window_origin((shader_window >> 12) & 0xf);
window_pixel_center pixelCenter = to_window_pixel_center(shader_window >> 16);
f32 offset_x = f32(method_registers[NV4097_SET_WINDOW_OFFSET] & 0xffff);
f32 offset_y = f32(method_registers[NV4097_SET_WINDOW_OFFSET] >> 16);
f32 offset_x = f32(method_registers.shader_window_offset_x());
f32 offset_y = f32(method_registers.shader_window_offset_y());
f32 scale_y = 1.0;
if (origin == window_origin::bottom)
@ -97,13 +95,13 @@ namespace rsx
void fill_viewport_matrix(void *buffer, bool transpose)
{
f32 offset_x = (f32&)method_registers[NV4097_SET_VIEWPORT_OFFSET + 0];
f32 offset_y = (f32&)method_registers[NV4097_SET_VIEWPORT_OFFSET + 1];
f32 offset_z = (f32&)method_registers[NV4097_SET_VIEWPORT_OFFSET + 2];
f32 offset_x = method_registers.viewport_offset_x();
f32 offset_y = method_registers.viewport_offset_y();
f32 offset_z = method_registers.viewport_offset_z();
f32 scale_x = (f32&)method_registers[NV4097_SET_VIEWPORT_SCALE + 0];
f32 scale_y = (f32&)method_registers[NV4097_SET_VIEWPORT_SCALE + 1];
f32 scale_z = (f32&)method_registers[NV4097_SET_VIEWPORT_SCALE + 2];
f32 scale_x = method_registers.viewport_scale_x();
f32 scale_y = method_registers.viewport_scale_y();
f32 scale_z = method_registers.viewport_scale_z();
fill_scale_offset_matrix(buffer, transpose, offset_x, offset_y, offset_z, scale_x, scale_y, scale_z);
}

View File

@ -0,0 +1,40 @@
#pragma once
#include "GCM.h"
#include "Utilities/types.h"
namespace rsx
{
struct data_array_format_info
{
private:
u8 index;
std::array<u32, 0x10000 / 4> &registers;
public:
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
vertex_base_type type = vertex_base_type::f;
data_array_format_info(u8 idx, std::array<u32, 0x10000 / 4> &r) : index(idx), registers(r)
{}
data_array_format_info() = delete;
void unpack_array(u32 data_array_format)
{
frequency = data_array_format >> 16;
stride = (data_array_format >> 8) & 0xff;
size = (data_array_format >> 4) & 0xf;
type = to_vertex_base_type(data_array_format & 0xf);
}
u32 offset() const
{
return registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
}
};
}

View File

@ -370,13 +370,13 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
if (event.GetId() == p_buffer_stencil->GetId()) display_buffer(this, stencil_img);
if (event.GetId() == p_buffer_tex->GetId())
{
u8 location = render->textures[m_cur_texture].location();
/* u8 location = render->textures[m_cur_texture].location();
if(location <= 1 && vm::check_addr(rsx::get_address(render->textures[m_cur_texture].offset(), location))
&& render->textures[m_cur_texture].width() && render->textures[m_cur_texture].height())
MemoryViewerPanel::ShowImage(this,
rsx::get_address(render->textures[m_cur_texture].offset(), location), 1,
render->textures[m_cur_texture].width(),
render->textures[m_cur_texture].height(), false);
render->textures[m_cur_texture].height(), false);*/
}
#undef SHOW_BUFFER
@ -725,7 +725,7 @@ void RSXDebugger::GetBuffers()
}
// Draw Texture
if(!render->textures[m_cur_texture].enabled())
/* if(!render->textures[m_cur_texture].enabled())
return;
u32 offset = render->textures[m_cur_texture].offset();
@ -752,7 +752,7 @@ void RSXDebugger::GetBuffers()
wxImage img(width, height, buffer);
wxClientDC dc_canvas(p_buffer_tex);
dc_canvas.DrawBitmap(img.Scale(m_text_width, m_text_height), 0, 0, false);
dc_canvas.DrawBitmap(img.Scale(m_text_width, m_text_height), 0, 0, false);*/
}
void RSXDebugger::GetFlags()
@ -823,7 +823,7 @@ void RSXDebugger::GetTexture()
for(uint i=0; i<rsx::limits::textures_count; ++i)
{
if(render->textures[i].enabled())
/* if(render->textures[i].enabled())
{
m_list_texture->InsertItem(i, wxString::Format("%d", i));
u8 location = render->textures[i].location();
@ -848,7 +848,7 @@ void RSXDebugger::GetTexture()
render->textures[i].height()));
m_list_texture->SetItemBackgroundColour(i, wxColour(m_cur_texture == i ? "Wheat" : "White"));
}
}*/
}
}

View File

@ -600,6 +600,7 @@
<ClInclude Include="Emu\DbgCommand.h" />
<ClInclude Include="Emu\Memory\wait_engine.h" />
<ClInclude Include="Emu\RSX\rsx_cache.h" />
<ClInclude Include="Emu\RSX\rsx_vertex_data.h" />
<ClInclude Include="Emu\VFS.h" />
<ClInclude Include="Emu\GameInfo.h" />
<ClInclude Include="Emu\IdManager.h" />

View File

@ -1687,5 +1687,8 @@
<ClInclude Include="..\Utilities\JIT.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\rsx_vertex_data.h">
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
</ItemGroup>
</Project>