Merge pull request #8766 from Kelebek1/regs
[video_core] Update 3D registers
This commit is contained in:
commit
55e6d0dae0
|
@ -994,13 +994,13 @@ void BufferCache<P>::BindHostIndexBuffer() {
|
||||||
const u32 size = index_buffer.size;
|
const u32 size = index_buffer.size;
|
||||||
SynchronizeBuffer(buffer, index_buffer.cpu_addr, size);
|
SynchronizeBuffer(buffer, index_buffer.cpu_addr, size);
|
||||||
if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
|
if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
|
||||||
const u32 new_offset = offset + maxwell3d->regs.index_array.first *
|
const u32 new_offset = offset + maxwell3d->regs.index_buffer.first *
|
||||||
maxwell3d->regs.index_array.FormatSizeInBytes();
|
maxwell3d->regs.index_buffer.FormatSizeInBytes();
|
||||||
runtime.BindIndexBuffer(buffer, new_offset, size);
|
runtime.BindIndexBuffer(buffer, new_offset, size);
|
||||||
} else {
|
} else {
|
||||||
runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_array.format,
|
runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format,
|
||||||
maxwell3d->regs.index_array.first,
|
maxwell3d->regs.index_buffer.first,
|
||||||
maxwell3d->regs.index_array.count, buffer, offset, size);
|
maxwell3d->regs.index_buffer.count, buffer, offset, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,7 +1017,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
|
||||||
}
|
}
|
||||||
flags[Dirty::VertexBuffer0 + index] = false;
|
flags[Dirty::VertexBuffer0 + index] = false;
|
||||||
|
|
||||||
const u32 stride = maxwell3d->regs.vertex_array[index].stride;
|
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
|
||||||
const u32 offset = buffer.Offset(binding.cpu_addr);
|
const u32 offset = buffer.Offset(binding.cpu_addr);
|
||||||
runtime.BindVertexBuffer(index, buffer, offset, binding.size, stride);
|
runtime.BindVertexBuffer(index, buffer, offset, binding.size, stride);
|
||||||
}
|
}
|
||||||
|
@ -1157,7 +1157,7 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindHostTransformFeedbackBuffers() {
|
void BufferCache<P>::BindHostTransformFeedbackBuffers() {
|
||||||
if (maxwell3d->regs.tfb_enabled == 0) {
|
if (maxwell3d->regs.transform_feedback_enabled == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||||
|
@ -1268,7 +1268,7 @@ template <class P>
|
||||||
void BufferCache<P>::UpdateIndexBuffer() {
|
void BufferCache<P>::UpdateIndexBuffer() {
|
||||||
// We have to check for the dirty flags and index count
|
// We have to check for the dirty flags and index count
|
||||||
// The index count is currently changed without updating the dirty flags
|
// The index count is currently changed without updating the dirty flags
|
||||||
const auto& index_array = maxwell3d->regs.index_array;
|
const auto& index_array = maxwell3d->regs.index_buffer;
|
||||||
auto& flags = maxwell3d->dirty.flags;
|
auto& flags = maxwell3d->dirty.flags;
|
||||||
if (!flags[Dirty::IndexBuffer] && last_index_count == index_array.count) {
|
if (!flags[Dirty::IndexBuffer] && last_index_count == index_array.count) {
|
||||||
return;
|
return;
|
||||||
|
@ -1311,10 +1311,10 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
|
||||||
if (!maxwell3d->dirty.flags[Dirty::VertexBuffer0 + index]) {
|
if (!maxwell3d->dirty.flags[Dirty::VertexBuffer0 + index]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& array = maxwell3d->regs.vertex_array[index];
|
const auto& array = maxwell3d->regs.vertex_streams[index];
|
||||||
const auto& limit = maxwell3d->regs.vertex_array_limit[index];
|
const auto& limit = maxwell3d->regs.vertex_stream_limits[index];
|
||||||
const GPUVAddr gpu_addr_begin = array.StartAddress();
|
const GPUVAddr gpu_addr_begin = array.Address();
|
||||||
const GPUVAddr gpu_addr_end = limit.LimitAddress() + 1;
|
const GPUVAddr gpu_addr_end = limit.Address() + 1;
|
||||||
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin);
|
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin);
|
||||||
u32 address_size = static_cast<u32>(
|
u32 address_size = static_cast<u32>(
|
||||||
std::min(gpu_addr_end - gpu_addr_begin, static_cast<u64>(std::numeric_limits<u32>::max())));
|
std::min(gpu_addr_end - gpu_addr_begin, static_cast<u64>(std::numeric_limits<u32>::max())));
|
||||||
|
@ -1380,7 +1380,7 @@ void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::UpdateTransformFeedbackBuffers() {
|
void BufferCache<P>::UpdateTransformFeedbackBuffers() {
|
||||||
if (maxwell3d->regs.tfb_enabled == 0) {
|
if (maxwell3d->regs.transform_feedback_enabled == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||||
|
@ -1390,11 +1390,11 @@ void BufferCache<P>::UpdateTransformFeedbackBuffers() {
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
|
void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
|
||||||
const auto& binding = maxwell3d->regs.tfb_bindings[index];
|
const auto& binding = maxwell3d->regs.transform_feedback.buffers[index];
|
||||||
const GPUVAddr gpu_addr = binding.Address() + binding.buffer_offset;
|
const GPUVAddr gpu_addr = binding.Address() + binding.start_offset;
|
||||||
const u32 size = binding.buffer_size;
|
const u32 size = binding.size;
|
||||||
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
|
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
|
||||||
if (binding.buffer_enable == 0 || size == 0 || !cpu_addr) {
|
if (binding.enable == 0 || size == 0 || !cpu_addr) {
|
||||||
transform_feedback_buffers[index] = NULL_BINDING;
|
transform_feedback_buffers[index] = NULL_BINDING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,21 +17,23 @@ using Tegra::Engines::Maxwell3D;
|
||||||
void SetupDirtyVertexBuffers(Maxwell3D::DirtyState::Tables& tables) {
|
void SetupDirtyVertexBuffers(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
static constexpr std::size_t num_array = 3;
|
static constexpr std::size_t num_array = 3;
|
||||||
for (std::size_t i = 0; i < Maxwell3D::Regs::NumVertexArrays; ++i) {
|
for (std::size_t i = 0; i < Maxwell3D::Regs::NumVertexArrays; ++i) {
|
||||||
const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[0]);
|
const std::size_t array_offset = OFF(vertex_streams) + i * NUM(vertex_streams[0]);
|
||||||
const std::size_t limit_offset = OFF(vertex_array_limit) + i * NUM(vertex_array_limit[0]);
|
const std::size_t limit_offset =
|
||||||
|
OFF(vertex_stream_limits) + i * NUM(vertex_stream_limits[0]);
|
||||||
|
|
||||||
FillBlock(tables, array_offset, num_array, VertexBuffer0 + i, VertexBuffers);
|
FillBlock(tables, array_offset, num_array, VertexBuffer0 + i, VertexBuffers);
|
||||||
FillBlock(tables, limit_offset, NUM(vertex_array_limit), VertexBuffer0 + i, VertexBuffers);
|
FillBlock(tables, limit_offset, NUM(vertex_stream_limits), VertexBuffer0 + i,
|
||||||
|
VertexBuffers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupIndexBuffer(Maxwell3D::DirtyState::Tables& tables) {
|
void SetupIndexBuffer(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
FillBlock(tables[0], OFF(index_array), NUM(index_array), IndexBuffer);
|
FillBlock(tables[0], OFF(index_buffer), NUM(index_buffer), IndexBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyDescriptors(Maxwell3D::DirtyState::Tables& tables) {
|
void SetupDirtyDescriptors(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
FillBlock(tables[0], OFF(tic), NUM(tic), Descriptors);
|
FillBlock(tables[0], OFF(tex_header), NUM(tex_header), Descriptors);
|
||||||
FillBlock(tables[0], OFF(tsc), NUM(tsc), Descriptors);
|
FillBlock(tables[0], OFF(tex_sampler), NUM(tex_sampler), Descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
|
void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
|
@ -42,7 +44,7 @@ void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
FillBlock(tables[0], begin + rt * num_per_rt, num_per_rt, ColorBuffer0 + rt);
|
FillBlock(tables[0], begin + rt * num_per_rt, num_per_rt, ColorBuffer0 + rt);
|
||||||
}
|
}
|
||||||
FillBlock(tables[1], begin, num, RenderTargets);
|
FillBlock(tables[1], begin, num, RenderTargets);
|
||||||
FillBlock(tables[0], OFF(render_area), NUM(render_area), RenderTargets);
|
FillBlock(tables[0], OFF(surface_clip), NUM(surface_clip), RenderTargets);
|
||||||
|
|
||||||
tables[0][OFF(rt_control)] = RenderTargets;
|
tables[0][OFF(rt_control)] = RenderTargets;
|
||||||
tables[1][OFF(rt_control)] = RenderTargetControl;
|
tables[1][OFF(rt_control)] = RenderTargetControl;
|
||||||
|
@ -52,15 +54,15 @@ void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
const u8 flag = zeta_flags[i];
|
const u8 flag = zeta_flags[i];
|
||||||
auto& table = tables[i];
|
auto& table = tables[i];
|
||||||
table[OFF(zeta_enable)] = flag;
|
table[OFF(zeta_enable)] = flag;
|
||||||
table[OFF(zeta_width)] = flag;
|
table[OFF(zeta_size.width)] = flag;
|
||||||
table[OFF(zeta_height)] = flag;
|
table[OFF(zeta_size.height)] = flag;
|
||||||
FillBlock(table, OFF(zeta), NUM(zeta), flag);
|
FillBlock(table, OFF(zeta), NUM(zeta), flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyShaders(Maxwell3D::DirtyState::Tables& tables) {
|
void SetupDirtyShaders(Maxwell3D::DirtyState::Tables& tables) {
|
||||||
FillBlock(tables[0], OFF(shader_config[0]),
|
FillBlock(tables[0], OFF(pipelines), NUM(pipelines) * Maxwell3D::Regs::MaxShaderProgram,
|
||||||
NUM(shader_config[0]) * Maxwell3D::Regs::MaxShaderProgram, Shaders);
|
Shaders);
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
|
|
@ -56,37 +56,37 @@ void Maxwell3D::InitializeRegisterDefaults() {
|
||||||
|
|
||||||
// Doom and Bomberman seems to use the uninitialized registers and just enable blend
|
// Doom and Bomberman seems to use the uninitialized registers and just enable blend
|
||||||
// so initialize blend registers with sane values
|
// so initialize blend registers with sane values
|
||||||
regs.blend.equation_rgb = Regs::Blend::Equation::Add;
|
regs.blend.color_op = Regs::Blend::Equation::Add_D3D;
|
||||||
regs.blend.factor_source_rgb = Regs::Blend::Factor::One;
|
regs.blend.color_source = Regs::Blend::Factor::One_D3D;
|
||||||
regs.blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
|
regs.blend.color_dest = Regs::Blend::Factor::Zero_D3D;
|
||||||
regs.blend.equation_a = Regs::Blend::Equation::Add;
|
regs.blend.alpha_op = Regs::Blend::Equation::Add_D3D;
|
||||||
regs.blend.factor_source_a = Regs::Blend::Factor::One;
|
regs.blend.alpha_source = Regs::Blend::Factor::One_D3D;
|
||||||
regs.blend.factor_dest_a = Regs::Blend::Factor::Zero;
|
regs.blend.alpha_dest = Regs::Blend::Factor::Zero_D3D;
|
||||||
for (auto& blend : regs.independent_blend) {
|
for (auto& blend : regs.blend_per_target) {
|
||||||
blend.equation_rgb = Regs::Blend::Equation::Add;
|
blend.color_op = Regs::Blend::Equation::Add_D3D;
|
||||||
blend.factor_source_rgb = Regs::Blend::Factor::One;
|
blend.color_source = Regs::Blend::Factor::One_D3D;
|
||||||
blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
|
blend.color_dest = Regs::Blend::Factor::Zero_D3D;
|
||||||
blend.equation_a = Regs::Blend::Equation::Add;
|
blend.alpha_op = Regs::Blend::Equation::Add_D3D;
|
||||||
blend.factor_source_a = Regs::Blend::Factor::One;
|
blend.alpha_source = Regs::Blend::Factor::One_D3D;
|
||||||
blend.factor_dest_a = Regs::Blend::Factor::Zero;
|
blend.alpha_dest = Regs::Blend::Factor::Zero_D3D;
|
||||||
}
|
}
|
||||||
regs.stencil_front_op_fail = Regs::StencilOp::Keep;
|
regs.stencil_front_op.fail = Regs::StencilOp::Op::Keep_D3D;
|
||||||
regs.stencil_front_op_zfail = Regs::StencilOp::Keep;
|
regs.stencil_front_op.zfail = Regs::StencilOp::Op::Keep_D3D;
|
||||||
regs.stencil_front_op_zpass = Regs::StencilOp::Keep;
|
regs.stencil_front_op.zpass = Regs::StencilOp::Op::Keep_D3D;
|
||||||
regs.stencil_front_func_func = Regs::ComparisonOp::Always;
|
regs.stencil_front_op.func = Regs::ComparisonOp::Always_GL;
|
||||||
regs.stencil_front_func_mask = 0xFFFFFFFF;
|
regs.stencil_front_func.func_mask = 0xFFFFFFFF;
|
||||||
regs.stencil_front_mask = 0xFFFFFFFF;
|
regs.stencil_front_func.mask = 0xFFFFFFFF;
|
||||||
regs.stencil_two_side_enable = 1;
|
regs.stencil_two_side_enable = 1;
|
||||||
regs.stencil_back_op_fail = Regs::StencilOp::Keep;
|
regs.stencil_back_op.fail = Regs::StencilOp::Op::Keep_D3D;
|
||||||
regs.stencil_back_op_zfail = Regs::StencilOp::Keep;
|
regs.stencil_back_op.zfail = Regs::StencilOp::Op::Keep_D3D;
|
||||||
regs.stencil_back_op_zpass = Regs::StencilOp::Keep;
|
regs.stencil_back_op.zpass = Regs::StencilOp::Op::Keep_D3D;
|
||||||
regs.stencil_back_func_func = Regs::ComparisonOp::Always;
|
regs.stencil_back_op.func = Regs::ComparisonOp::Always_GL;
|
||||||
regs.stencil_back_func_mask = 0xFFFFFFFF;
|
regs.stencil_back_func.func_mask = 0xFFFFFFFF;
|
||||||
regs.stencil_back_mask = 0xFFFFFFFF;
|
regs.stencil_back_func.mask = 0xFFFFFFFF;
|
||||||
|
|
||||||
regs.depth_test_func = Regs::ComparisonOp::Always;
|
regs.depth_test_func = Regs::ComparisonOp::Always_GL;
|
||||||
regs.front_face = Regs::FrontFace::CounterClockWise;
|
regs.gl_front_face = Regs::FrontFace::CounterClockWise;
|
||||||
regs.cull_face = Regs::CullFace::Back;
|
regs.gl_cull_face = Regs::CullFace::Back;
|
||||||
|
|
||||||
// TODO(Rodrigo): Most games do not set a point size. I think this is a case of a
|
// TODO(Rodrigo): Most games do not set a point size. I think this is a case of a
|
||||||
// register carrying a default value. Assume it's OpenGL's default (1).
|
// register carrying a default value. Assume it's OpenGL's default (1).
|
||||||
|
@ -107,20 +107,20 @@ void Maxwell3D::InitializeRegisterDefaults() {
|
||||||
|
|
||||||
// NVN games expect these values to be enabled at boot
|
// NVN games expect these values to be enabled at boot
|
||||||
regs.rasterize_enable = 1;
|
regs.rasterize_enable = 1;
|
||||||
regs.rt_separate_frag_data = 1;
|
regs.color_target_mrt_enable = 1;
|
||||||
regs.framebuffer_srgb = 1;
|
regs.framebuffer_srgb = 1;
|
||||||
regs.line_width_aliased = 1.0f;
|
regs.line_width_aliased = 1.0f;
|
||||||
regs.line_width_smooth = 1.0f;
|
regs.line_width_smooth = 1.0f;
|
||||||
regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise;
|
regs.gl_front_face = Maxwell3D::Regs::FrontFace::ClockWise;
|
||||||
regs.polygon_mode_back = Maxwell3D::Regs::PolygonMode::Fill;
|
regs.polygon_mode_back = Maxwell3D::Regs::PolygonMode::Fill;
|
||||||
regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill;
|
regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill;
|
||||||
|
|
||||||
shadow_state = regs;
|
shadow_state = regs;
|
||||||
|
|
||||||
mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true;
|
mme_inline[MAXWELL3D_REG_INDEX(draw.end)] = true;
|
||||||
mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true;
|
mme_inline[MAXWELL3D_REG_INDEX(draw.begin)] = true;
|
||||||
mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
|
mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
|
||||||
mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true;
|
mme_inline[MAXWELL3D_REG_INDEX(index_buffer.count)] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
|
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
|
||||||
|
@ -173,51 +173,56 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
|
||||||
case MAXWELL3D_REG_INDEX(shadow_ram_control):
|
case MAXWELL3D_REG_INDEX(shadow_ram_control):
|
||||||
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument);
|
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument);
|
||||||
return;
|
return;
|
||||||
case MAXWELL3D_REG_INDEX(macros.upload_address):
|
case MAXWELL3D_REG_INDEX(load_mme.instruction_ptr):
|
||||||
return macro_engine->ClearCode(regs.macros.upload_address);
|
return macro_engine->ClearCode(regs.load_mme.instruction_ptr);
|
||||||
case MAXWELL3D_REG_INDEX(macros.data):
|
case MAXWELL3D_REG_INDEX(load_mme.instruction):
|
||||||
return macro_engine->AddCode(regs.macros.upload_address, argument);
|
return macro_engine->AddCode(regs.load_mme.instruction_ptr, argument);
|
||||||
case MAXWELL3D_REG_INDEX(macros.bind):
|
case MAXWELL3D_REG_INDEX(load_mme.start_address):
|
||||||
return ProcessMacroBind(argument);
|
return ProcessMacroBind(argument);
|
||||||
case MAXWELL3D_REG_INDEX(firmware[4]):
|
case MAXWELL3D_REG_INDEX(falcon[4]):
|
||||||
return ProcessFirmwareCall4();
|
return ProcessFirmwareCall4();
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data):
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer):
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 1:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 1:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 2:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 2:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 3:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 3:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 4:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 4:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 5:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 5:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 6:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 6:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 7:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 7:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 8:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 8:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 9:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 9:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 10:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 10:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 11:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 11:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 12:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 12:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 13:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 14:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 15:
|
||||||
return ProcessCBData(argument);
|
return ProcessCBData(argument);
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[0]):
|
case MAXWELL3D_REG_INDEX(bind_groups[0].raw_config):
|
||||||
return ProcessCBBind(0);
|
return ProcessCBBind(0);
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[1]):
|
case MAXWELL3D_REG_INDEX(bind_groups[1].raw_config):
|
||||||
return ProcessCBBind(1);
|
return ProcessCBBind(1);
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[2]):
|
case MAXWELL3D_REG_INDEX(bind_groups[2].raw_config):
|
||||||
return ProcessCBBind(2);
|
return ProcessCBBind(2);
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[3]):
|
case MAXWELL3D_REG_INDEX(bind_groups[3].raw_config):
|
||||||
return ProcessCBBind(3);
|
return ProcessCBBind(3);
|
||||||
case MAXWELL3D_REG_INDEX(cb_bind[4]):
|
case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config):
|
||||||
return ProcessCBBind(4);
|
return ProcessCBBind(4);
|
||||||
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl):
|
case MAXWELL3D_REG_INDEX(draw.end):
|
||||||
return DrawArrays();
|
return DrawArrays();
|
||||||
case MAXWELL3D_REG_INDEX(small_index):
|
case MAXWELL3D_REG_INDEX(index_buffer32_first):
|
||||||
regs.index_array.count = regs.small_index.count;
|
regs.index_buffer.count = regs.index_buffer32_first.count;
|
||||||
regs.index_array.first = regs.small_index.first;
|
regs.index_buffer.first = regs.index_buffer32_first.first;
|
||||||
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
return DrawArrays();
|
return DrawArrays();
|
||||||
case MAXWELL3D_REG_INDEX(small_index_2):
|
case MAXWELL3D_REG_INDEX(index_buffer16_first):
|
||||||
regs.index_array.count = regs.small_index_2.count;
|
regs.index_buffer.count = regs.index_buffer16_first.count;
|
||||||
regs.index_array.first = regs.small_index_2.first;
|
regs.index_buffer.first = regs.index_buffer16_first.first;
|
||||||
|
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
|
return DrawArrays();
|
||||||
|
case MAXWELL3D_REG_INDEX(index_buffer8_first):
|
||||||
|
regs.index_buffer.count = regs.index_buffer8_first.count;
|
||||||
|
regs.index_buffer.first = regs.index_buffer8_first.first;
|
||||||
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
// a macro calls this one over and over, should it increase instancing?
|
// a macro calls this one over and over, should it increase instancing?
|
||||||
// Used by Hades and likely other Vulkan games.
|
// Used by Hades and likely other Vulkan games.
|
||||||
|
@ -225,28 +230,24 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
|
||||||
case MAXWELL3D_REG_INDEX(topology_override):
|
case MAXWELL3D_REG_INDEX(topology_override):
|
||||||
use_topology_override = true;
|
use_topology_override = true;
|
||||||
return;
|
return;
|
||||||
case MAXWELL3D_REG_INDEX(clear_buffers):
|
case MAXWELL3D_REG_INDEX(clear_surface):
|
||||||
return ProcessClearBuffers();
|
return ProcessClearBuffers();
|
||||||
case MAXWELL3D_REG_INDEX(query.query_get):
|
case MAXWELL3D_REG_INDEX(report_semaphore.query):
|
||||||
return ProcessQueryGet();
|
return ProcessQueryGet();
|
||||||
case MAXWELL3D_REG_INDEX(condition.mode):
|
case MAXWELL3D_REG_INDEX(render_enable.mode):
|
||||||
return ProcessQueryCondition();
|
return ProcessQueryCondition();
|
||||||
case MAXWELL3D_REG_INDEX(counter_reset):
|
case MAXWELL3D_REG_INDEX(clear_report_value):
|
||||||
return ProcessCounterReset();
|
return ProcessCounterReset();
|
||||||
case MAXWELL3D_REG_INDEX(sync_info):
|
case MAXWELL3D_REG_INDEX(sync_info):
|
||||||
return ProcessSyncPoint();
|
return ProcessSyncPoint();
|
||||||
case MAXWELL3D_REG_INDEX(exec_upload):
|
case MAXWELL3D_REG_INDEX(launch_dma):
|
||||||
return upload_state.ProcessExec(regs.exec_upload.linear != 0);
|
return upload_state.ProcessExec(regs.launch_dma.memory_layout.Value() ==
|
||||||
case MAXWELL3D_REG_INDEX(data_upload):
|
Regs::LaunchDMA::Layout::Pitch);
|
||||||
|
case MAXWELL3D_REG_INDEX(inline_data):
|
||||||
upload_state.ProcessData(argument, is_last_call);
|
upload_state.ProcessData(argument, is_last_call);
|
||||||
return;
|
return;
|
||||||
case MAXWELL3D_REG_INDEX(fragment_barrier):
|
case MAXWELL3D_REG_INDEX(fragment_barrier):
|
||||||
return rasterizer->FragmentBarrier();
|
return rasterizer->FragmentBarrier();
|
||||||
case MAXWELL3D_REG_INDEX(invalidate_texture_data_cache):
|
|
||||||
rasterizer->InvalidateGPUCache();
|
|
||||||
return rasterizer->WaitForIdle();
|
|
||||||
case MAXWELL3D_REG_INDEX(tiled_cache_barrier):
|
|
||||||
return rasterizer->TiledCacheBarrier();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,25 +297,25 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data):
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer):
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 1:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 1:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 2:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 2:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 3:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 3:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 4:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 4:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 5:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 5:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 6:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 6:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 7:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 7:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 8:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 8:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 9:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 9:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 10:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 10:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 11:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 11:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 12:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 12:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 13:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 14:
|
||||||
case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15:
|
case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 15:
|
||||||
ProcessCBMultiData(base_start, amount);
|
ProcessCBMultiData(base_start, amount);
|
||||||
break;
|
break;
|
||||||
case MAXWELL3D_REG_INDEX(data_upload):
|
case MAXWELL3D_REG_INDEX(inline_data):
|
||||||
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
|
upload_state.ProcessData(base_start, static_cast<size_t>(amount));
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
@ -353,14 +354,15 @@ void Maxwell3D::CallMethodFromMME(u32 method, u32 method_argument) {
|
||||||
if (mme_inline[method]) {
|
if (mme_inline[method]) {
|
||||||
regs.reg_array[method] = method_argument;
|
regs.reg_array[method] = method_argument;
|
||||||
if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count) ||
|
if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count) ||
|
||||||
method == MAXWELL3D_REG_INDEX(index_array.count)) {
|
method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
|
||||||
const MMEDrawMode expected_mode = method == MAXWELL3D_REG_INDEX(vertex_buffer.count)
|
const MMEDrawMode expected_mode = method == MAXWELL3D_REG_INDEX(vertex_buffer.count)
|
||||||
? MMEDrawMode::Array
|
? MMEDrawMode::Array
|
||||||
: MMEDrawMode::Indexed;
|
: MMEDrawMode::Indexed;
|
||||||
StepInstance(expected_mode, method_argument);
|
StepInstance(expected_mode, method_argument);
|
||||||
} else if (method == MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)) {
|
} else if (method == MAXWELL3D_REG_INDEX(draw.begin)) {
|
||||||
mme_draw.instance_mode =
|
mme_draw.instance_mode =
|
||||||
(regs.draw.instance_next != 0) || (regs.draw.instance_cont != 0);
|
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
|
||||||
|
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged);
|
||||||
mme_draw.gl_begin_consume = true;
|
mme_draw.gl_begin_consume = true;
|
||||||
} else {
|
} else {
|
||||||
mme_draw.gl_end_count++;
|
mme_draw.gl_end_count++;
|
||||||
|
@ -405,11 +407,12 @@ void Maxwell3D::ProcessTopologyOverride() {
|
||||||
void Maxwell3D::FlushMMEInlineDraw() {
|
void Maxwell3D::FlushMMEInlineDraw() {
|
||||||
LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
|
LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
|
||||||
regs.vertex_buffer.count);
|
regs.vertex_buffer.count);
|
||||||
ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
|
ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
|
||||||
ASSERT(mme_draw.instance_count == mme_draw.gl_end_count);
|
ASSERT(mme_draw.instance_count == mme_draw.gl_end_count);
|
||||||
|
|
||||||
// Both instance configuration registers can not be set at the same time.
|
// Both instance configuration registers can not be set at the same time.
|
||||||
ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
|
ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
|
||||||
|
regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
|
||||||
"Illegal combination of instancing parameters");
|
"Illegal combination of instancing parameters");
|
||||||
|
|
||||||
ProcessTopologyOverride();
|
ProcessTopologyOverride();
|
||||||
|
@ -424,7 +427,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
|
||||||
// it's possible that it is incorrect and that there is some other register used to specify the
|
// it's possible that it is incorrect and that there is some other register used to specify the
|
||||||
// drawing mode.
|
// drawing mode.
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
regs.index_array.count = 0;
|
regs.index_buffer.count = 0;
|
||||||
} else {
|
} else {
|
||||||
regs.vertex_buffer.count = 0;
|
regs.vertex_buffer.count = 0;
|
||||||
}
|
}
|
||||||
|
@ -437,11 +440,11 @@ void Maxwell3D::FlushMMEInlineDraw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessMacroUpload(u32 data) {
|
void Maxwell3D::ProcessMacroUpload(u32 data) {
|
||||||
macro_engine->AddCode(regs.macros.upload_address++, data);
|
macro_engine->AddCode(regs.load_mme.instruction_ptr++, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessMacroBind(u32 data) {
|
void Maxwell3D::ProcessMacroBind(u32 data) {
|
||||||
macro_positions[regs.macros.entry++] = data;
|
macro_positions[regs.load_mme.start_address_ptr++] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessFirmwareCall4() {
|
void Maxwell3D::ProcessFirmwareCall4() {
|
||||||
|
@ -449,11 +452,11 @@ void Maxwell3D::ProcessFirmwareCall4() {
|
||||||
|
|
||||||
// Firmware call 4 is a blob that changes some registers depending on its parameters.
|
// Firmware call 4 is a blob that changes some registers depending on its parameters.
|
||||||
// These registers don't affect emulation and so are stubbed by setting 0xd00 to 1.
|
// These registers don't affect emulation and so are stubbed by setting 0xd00 to 1.
|
||||||
regs.reg_array[0xd00] = 1;
|
regs.shadow_scratch[0] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
|
void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
|
||||||
const GPUVAddr sequence_address{regs.query.QueryAddress()};
|
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
|
||||||
if (long_query) {
|
if (long_query) {
|
||||||
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
|
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
|
||||||
memory_manager.Write<u64>(sequence_address, payload);
|
memory_manager.Write<u64>(sequence_address, payload);
|
||||||
|
@ -464,15 +467,17 @@ void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
|
||||||
|
|
||||||
void Maxwell3D::ProcessQueryGet() {
|
void Maxwell3D::ProcessQueryGet() {
|
||||||
// TODO(Subv): Support the other query units.
|
// TODO(Subv): Support the other query units.
|
||||||
if (regs.query.query_get.unit != Regs::QueryUnit::Crop) {
|
if (regs.report_semaphore.query.location != Regs::ReportSemaphore::Location::All) {
|
||||||
LOG_DEBUG(HW_GPU, "Units other than CROP are unimplemented");
|
LOG_DEBUG(HW_GPU, "Locations other than ALL are unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (regs.query.query_get.operation) {
|
switch (regs.report_semaphore.query.operation) {
|
||||||
case Regs::QueryOperation::Release:
|
case Regs::ReportSemaphore::Operation::Release:
|
||||||
if (regs.query.query_get.fence == 1 || regs.query.query_get.short_query != 0) {
|
if (regs.report_semaphore.query.release ==
|
||||||
const GPUVAddr sequence_address{regs.query.QueryAddress()};
|
Regs::ReportSemaphore::Release::AfterAllPreceedingWrites ||
|
||||||
const u32 payload = regs.query.query_sequence;
|
regs.report_semaphore.query.short_query != 0) {
|
||||||
|
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
|
||||||
|
const u32 payload = regs.report_semaphore.payload;
|
||||||
std::function<void()> operation([this, sequence_address, payload] {
|
std::function<void()> operation([this, sequence_address, payload] {
|
||||||
memory_manager.Write<u32>(sequence_address, payload);
|
memory_manager.Write<u32>(sequence_address, payload);
|
||||||
});
|
});
|
||||||
|
@ -482,8 +487,8 @@ void Maxwell3D::ProcessQueryGet() {
|
||||||
u64_le value;
|
u64_le value;
|
||||||
u64_le timestamp;
|
u64_le timestamp;
|
||||||
};
|
};
|
||||||
const GPUVAddr sequence_address{regs.query.QueryAddress()};
|
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
|
||||||
const u32 payload = regs.query.query_sequence;
|
const u32 payload = regs.report_semaphore.payload;
|
||||||
std::function<void()> operation([this, sequence_address, payload] {
|
std::function<void()> operation([this, sequence_address, payload] {
|
||||||
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
|
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
|
||||||
memory_manager.Write<u64>(sequence_address, payload);
|
memory_manager.Write<u64>(sequence_address, payload);
|
||||||
|
@ -491,19 +496,19 @@ void Maxwell3D::ProcessQueryGet() {
|
||||||
rasterizer->SyncOperation(std::move(operation));
|
rasterizer->SyncOperation(std::move(operation));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Regs::QueryOperation::Acquire:
|
case Regs::ReportSemaphore::Operation::Acquire:
|
||||||
// TODO(Blinkhawk): Under this operation, the GPU waits for the CPU to write a value that
|
// TODO(Blinkhawk): Under this operation, the GPU waits for the CPU to write a value that
|
||||||
// matches the current payload.
|
// matches the current payload.
|
||||||
UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE");
|
UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE");
|
||||||
break;
|
break;
|
||||||
case Regs::QueryOperation::Counter:
|
case Regs::ReportSemaphore::Operation::ReportOnly:
|
||||||
if (const std::optional<u64> result = GetQueryResult()) {
|
if (const std::optional<u64> result = GetQueryResult()) {
|
||||||
// If the query returns an empty optional it means it's cached and deferred.
|
// If the query returns an empty optional it means it's cached and deferred.
|
||||||
// In this case we have a non-empty result, so we stamp it immediately.
|
// In this case we have a non-empty result, so we stamp it immediately.
|
||||||
StampQueryResult(*result, regs.query.query_get.short_query == 0);
|
StampQueryResult(*result, regs.report_semaphore.query.short_query == 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Regs::QueryOperation::Trap:
|
case Regs::ReportSemaphore::Operation::Trap:
|
||||||
UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
|
UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -513,31 +518,31 @@ void Maxwell3D::ProcessQueryGet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessQueryCondition() {
|
void Maxwell3D::ProcessQueryCondition() {
|
||||||
const GPUVAddr condition_address{regs.condition.Address()};
|
const GPUVAddr condition_address{regs.render_enable.Address()};
|
||||||
switch (regs.condition.mode) {
|
switch (regs.render_enable.mode) {
|
||||||
case Regs::ConditionMode::Always: {
|
case Regs::RenderEnable::Mode::True: {
|
||||||
execute_on = true;
|
execute_on = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Regs::ConditionMode::Never: {
|
case Regs::RenderEnable::Mode::False: {
|
||||||
execute_on = false;
|
execute_on = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Regs::ConditionMode::ResNonZero: {
|
case Regs::RenderEnable::Mode::Conditional: {
|
||||||
Regs::QueryCompare cmp;
|
Regs::ReportSemaphore::Compare cmp;
|
||||||
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
|
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
|
||||||
execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
|
execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Regs::ConditionMode::Equal: {
|
case Regs::RenderEnable::Mode::IfEqual: {
|
||||||
Regs::QueryCompare cmp;
|
Regs::ReportSemaphore::Compare cmp;
|
||||||
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
|
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
|
||||||
execute_on =
|
execute_on =
|
||||||
cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode;
|
cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Regs::ConditionMode::NotEqual: {
|
case Regs::RenderEnable::Mode::IfNotEqual: {
|
||||||
Regs::QueryCompare cmp;
|
Regs::ReportSemaphore::Compare cmp;
|
||||||
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
|
memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
|
||||||
execute_on =
|
execute_on =
|
||||||
cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
|
cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
|
||||||
|
@ -552,21 +557,21 @@ void Maxwell3D::ProcessQueryCondition() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessCounterReset() {
|
void Maxwell3D::ProcessCounterReset() {
|
||||||
switch (regs.counter_reset) {
|
switch (regs.clear_report_value) {
|
||||||
case Regs::CounterReset::SampleCnt:
|
case Regs::ClearReport::ZPassPixelCount:
|
||||||
rasterizer->ResetCounter(QueryType::SamplesPassed);
|
rasterizer->ResetCounter(QueryType::SamplesPassed);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.counter_reset);
|
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.clear_report_value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessSyncPoint() {
|
void Maxwell3D::ProcessSyncPoint() {
|
||||||
const u32 sync_point = regs.sync_info.sync_point.Value();
|
const u32 sync_point = regs.sync_info.sync_point.Value();
|
||||||
const u32 increment = regs.sync_info.increment.Value();
|
const auto condition = regs.sync_info.condition.Value();
|
||||||
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
|
[[maybe_unused]] const u32 cache_flush = regs.sync_info.clean_l2.Value();
|
||||||
if (increment) {
|
if (condition == Regs::SyncInfo::Condition::RopWritesDone) {
|
||||||
rasterizer->SignalSyncPoint(sync_point);
|
rasterizer->SignalSyncPoint(sync_point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,23 +579,24 @@ void Maxwell3D::ProcessSyncPoint() {
|
||||||
void Maxwell3D::DrawArrays() {
|
void Maxwell3D::DrawArrays() {
|
||||||
LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
|
LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
|
||||||
regs.vertex_buffer.count);
|
regs.vertex_buffer.count);
|
||||||
ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
|
ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
|
||||||
|
|
||||||
// Both instance configuration registers can not be set at the same time.
|
// Both instance configuration registers can not be set at the same time.
|
||||||
ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
|
ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
|
||||||
|
regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
|
||||||
"Illegal combination of instancing parameters");
|
"Illegal combination of instancing parameters");
|
||||||
|
|
||||||
ProcessTopologyOverride();
|
ProcessTopologyOverride();
|
||||||
|
|
||||||
if (regs.draw.instance_next) {
|
if (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) {
|
||||||
// Increment the current instance *before* drawing.
|
// Increment the current instance *before* drawing.
|
||||||
state.current_instance += 1;
|
state.current_instance++;
|
||||||
} else if (!regs.draw.instance_cont) {
|
} else if (regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged) {
|
||||||
// Reset the current instance to 0.
|
// Reset the current instance to 0.
|
||||||
state.current_instance = 0;
|
state.current_instance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
|
const bool is_indexed{regs.index_buffer.count && !regs.vertex_buffer.count};
|
||||||
if (ShouldExecute()) {
|
if (ShouldExecute()) {
|
||||||
rasterizer->Draw(is_indexed, false);
|
rasterizer->Draw(is_indexed, false);
|
||||||
}
|
}
|
||||||
|
@ -600,60 +606,60 @@ void Maxwell3D::DrawArrays() {
|
||||||
// it's possible that it is incorrect and that there is some other register used to specify the
|
// it's possible that it is incorrect and that there is some other register used to specify the
|
||||||
// drawing mode.
|
// drawing mode.
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
regs.index_array.count = 0;
|
regs.index_buffer.count = 0;
|
||||||
} else {
|
} else {
|
||||||
regs.vertex_buffer.count = 0;
|
regs.vertex_buffer.count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u64> Maxwell3D::GetQueryResult() {
|
std::optional<u64> Maxwell3D::GetQueryResult() {
|
||||||
switch (regs.query.query_get.select) {
|
switch (regs.report_semaphore.query.report) {
|
||||||
case Regs::QuerySelect::Payload:
|
case Regs::ReportSemaphore::Report::Payload:
|
||||||
return regs.query.query_sequence;
|
return regs.report_semaphore.payload;
|
||||||
case Regs::QuerySelect::SamplesPassed:
|
case Regs::ReportSemaphore::Report::ZPassPixelCount64:
|
||||||
// Deferred.
|
// Deferred.
|
||||||
rasterizer->Query(regs.query.QueryAddress(), QueryType::SamplesPassed,
|
rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed,
|
||||||
system.GPU().GetTicks());
|
system.GPU().GetTicks());
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
default:
|
default:
|
||||||
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
|
LOG_DEBUG(HW_GPU, "Unimplemented query report type {}",
|
||||||
regs.query.query_get.select.Value());
|
regs.report_semaphore.query.report.Value());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessCBBind(size_t stage_index) {
|
void Maxwell3D::ProcessCBBind(size_t stage_index) {
|
||||||
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
|
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
|
||||||
const auto& bind_data = regs.cb_bind[stage_index];
|
const auto& bind_data = regs.bind_groups[stage_index];
|
||||||
auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.index];
|
auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.shader_slot];
|
||||||
buffer.enabled = bind_data.valid.Value() != 0;
|
buffer.enabled = bind_data.valid.Value() != 0;
|
||||||
buffer.address = regs.const_buffer.BufferAddress();
|
buffer.address = regs.const_buffer.Address();
|
||||||
buffer.size = regs.const_buffer.cb_size;
|
buffer.size = regs.const_buffer.size;
|
||||||
|
|
||||||
const bool is_enabled = bind_data.valid.Value() != 0;
|
const bool is_enabled = bind_data.valid.Value() != 0;
|
||||||
if (!is_enabled) {
|
if (!is_enabled) {
|
||||||
rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.index);
|
rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.shader_slot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const GPUVAddr gpu_addr = regs.const_buffer.BufferAddress();
|
const GPUVAddr gpu_addr = regs.const_buffer.Address();
|
||||||
const u32 size = regs.const_buffer.cb_size;
|
const u32 size = regs.const_buffer.size;
|
||||||
rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.index, gpu_addr, size);
|
rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.shader_slot, gpu_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessCBMultiData(const u32* start_base, u32 amount) {
|
void Maxwell3D::ProcessCBMultiData(const u32* start_base, u32 amount) {
|
||||||
// Write the input value to the current const buffer at the current position.
|
// Write the input value to the current const buffer at the current position.
|
||||||
const GPUVAddr buffer_address = regs.const_buffer.BufferAddress();
|
const GPUVAddr buffer_address = regs.const_buffer.Address();
|
||||||
ASSERT(buffer_address != 0);
|
ASSERT(buffer_address != 0);
|
||||||
|
|
||||||
// Don't allow writing past the end of the buffer.
|
// Don't allow writing past the end of the buffer.
|
||||||
ASSERT(regs.const_buffer.cb_pos <= regs.const_buffer.cb_size);
|
ASSERT(regs.const_buffer.offset <= regs.const_buffer.size);
|
||||||
|
|
||||||
const GPUVAddr address{buffer_address + regs.const_buffer.cb_pos};
|
const GPUVAddr address{buffer_address + regs.const_buffer.offset};
|
||||||
const size_t copy_size = amount * sizeof(u32);
|
const size_t copy_size = amount * sizeof(u32);
|
||||||
memory_manager.WriteBlock(address, start_base, copy_size);
|
memory_manager.WriteBlock(address, start_base, copy_size);
|
||||||
|
|
||||||
// Increment the current buffer position.
|
// Increment the current buffer position.
|
||||||
regs.const_buffer.cb_pos += static_cast<u32>(copy_size);
|
regs.const_buffer.offset += static_cast<u32>(copy_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessCBData(u32 value) {
|
void Maxwell3D::ProcessCBData(u32 value) {
|
||||||
|
@ -661,7 +667,8 @@ void Maxwell3D::ProcessCBData(u32 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
|
Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
|
||||||
const GPUVAddr tic_address_gpu{regs.tic.Address() + tic_index * sizeof(Texture::TICEntry)};
|
const GPUVAddr tic_address_gpu{regs.tex_header.Address() +
|
||||||
|
tic_index * sizeof(Texture::TICEntry)};
|
||||||
|
|
||||||
Texture::TICEntry tic_entry;
|
Texture::TICEntry tic_entry;
|
||||||
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
|
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
|
||||||
|
@ -670,7 +677,8 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
|
Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
|
||||||
const GPUVAddr tsc_address_gpu{regs.tsc.Address() + tsc_index * sizeof(Texture::TSCEntry)};
|
const GPUVAddr tsc_address_gpu{regs.tex_sampler.Address() +
|
||||||
|
tsc_index * sizeof(Texture::TSCEntry)};
|
||||||
|
|
||||||
Texture::TSCEntry tsc_entry;
|
Texture::TSCEntry tsc_entry;
|
||||||
memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry));
|
memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry));
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,11 +24,15 @@ namespace Tegra {
|
||||||
class DmaPusher;
|
class DmaPusher;
|
||||||
struct CommandList;
|
struct CommandList;
|
||||||
|
|
||||||
|
// TODO: Implement the commented ones
|
||||||
enum class RenderTargetFormat : u32 {
|
enum class RenderTargetFormat : u32 {
|
||||||
NONE = 0x0,
|
NONE = 0x0,
|
||||||
R32B32G32A32_FLOAT = 0xC0,
|
R32B32G32A32_FLOAT = 0xC0,
|
||||||
R32G32B32A32_SINT = 0xC1,
|
R32G32B32A32_SINT = 0xC1,
|
||||||
R32G32B32A32_UINT = 0xC2,
|
R32G32B32A32_UINT = 0xC2,
|
||||||
|
// R32G32B32X32_FLOAT = 0xC3,
|
||||||
|
// R32G32B32X32_SINT = 0xC4,
|
||||||
|
// R32G32B32X32_UINT = 0xC5,
|
||||||
R16G16B16A16_UNORM = 0xC6,
|
R16G16B16A16_UNORM = 0xC6,
|
||||||
R16G16B16A16_SNORM = 0xC7,
|
R16G16B16A16_SNORM = 0xC7,
|
||||||
R16G16B16A16_SINT = 0xC8,
|
R16G16B16A16_SINT = 0xC8,
|
||||||
|
@ -38,8 +42,8 @@ enum class RenderTargetFormat : u32 {
|
||||||
R32G32_SINT = 0xCC,
|
R32G32_SINT = 0xCC,
|
||||||
R32G32_UINT = 0xCD,
|
R32G32_UINT = 0xCD,
|
||||||
R16G16B16X16_FLOAT = 0xCE,
|
R16G16B16X16_FLOAT = 0xCE,
|
||||||
B8G8R8A8_UNORM = 0xCF,
|
A8R8G8B8_UNORM = 0xCF,
|
||||||
B8G8R8A8_SRGB = 0xD0,
|
A8R8G8B8_SRGB = 0xD0,
|
||||||
A2B10G10R10_UNORM = 0xD1,
|
A2B10G10R10_UNORM = 0xD1,
|
||||||
A2B10G10R10_UINT = 0xD2,
|
A2B10G10R10_UINT = 0xD2,
|
||||||
A8B8G8R8_UNORM = 0xD5,
|
A8B8G8R8_UNORM = 0xD5,
|
||||||
|
@ -52,10 +56,13 @@ enum class RenderTargetFormat : u32 {
|
||||||
R16G16_SINT = 0xDC,
|
R16G16_SINT = 0xDC,
|
||||||
R16G16_UINT = 0xDD,
|
R16G16_UINT = 0xDD,
|
||||||
R16G16_FLOAT = 0xDE,
|
R16G16_FLOAT = 0xDE,
|
||||||
|
// A2R10G10B10_UNORM = 0xDF,
|
||||||
B10G11R11_FLOAT = 0xE0,
|
B10G11R11_FLOAT = 0xE0,
|
||||||
R32_SINT = 0xE3,
|
R32_SINT = 0xE3,
|
||||||
R32_UINT = 0xE4,
|
R32_UINT = 0xE4,
|
||||||
R32_FLOAT = 0xE5,
|
R32_FLOAT = 0xE5,
|
||||||
|
// X8R8G8B8_UNORM = 0xE6,
|
||||||
|
// X8R8G8B8_SRGB = 0xE7,
|
||||||
R5G6B5_UNORM = 0xE8,
|
R5G6B5_UNORM = 0xE8,
|
||||||
A1R5G5B5_UNORM = 0xE9,
|
A1R5G5B5_UNORM = 0xE9,
|
||||||
R8G8_UNORM = 0xEA,
|
R8G8_UNORM = 0xEA,
|
||||||
|
@ -71,17 +78,42 @@ enum class RenderTargetFormat : u32 {
|
||||||
R8_SNORM = 0xF4,
|
R8_SNORM = 0xF4,
|
||||||
R8_SINT = 0xF5,
|
R8_SINT = 0xF5,
|
||||||
R8_UINT = 0xF6,
|
R8_UINT = 0xF6,
|
||||||
|
|
||||||
|
/*
|
||||||
|
A8_UNORM = 0xF7,
|
||||||
|
X1R5G5B5_UNORM = 0xF8,
|
||||||
|
X8B8G8R8_UNORM = 0xF9,
|
||||||
|
X8B8G8R8_SRGB = 0xFA,
|
||||||
|
Z1R5G5B5_UNORM = 0xFB,
|
||||||
|
O1R5G5B5_UNORM = 0xFC,
|
||||||
|
Z8R8G8B8_UNORM = 0xFD,
|
||||||
|
O8R8G8B8_UNORM = 0xFE,
|
||||||
|
R32_UNORM = 0xFF,
|
||||||
|
A16_UNORM = 0x40,
|
||||||
|
A16_FLOAT = 0x41,
|
||||||
|
A32_FLOAT = 0x42,
|
||||||
|
A8R8_UNORM = 0x43,
|
||||||
|
R16A16_UNORM = 0x44,
|
||||||
|
R16A16_FLOAT = 0x45,
|
||||||
|
R32A32_FLOAT = 0x46,
|
||||||
|
B8G8R8A8_UNORM = 0x47,
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DepthFormat : u32 {
|
enum class DepthFormat : u32 {
|
||||||
D32_FLOAT = 0xA,
|
Z32_FLOAT = 0xA,
|
||||||
D16_UNORM = 0x13,
|
Z16_UNORM = 0x13,
|
||||||
S8_UINT_Z24_UNORM = 0x14,
|
Z24_UNORM_S8_UINT = 0x14,
|
||||||
D24X8_UNORM = 0x15,
|
X8Z24_UNORM = 0x15,
|
||||||
D24S8_UNORM = 0x16,
|
S8Z24_UNORM = 0x16,
|
||||||
S8_UINT = 0x17,
|
S8_UINT = 0x17,
|
||||||
D24C8_UNORM = 0x18,
|
V8Z24_UNORM = 0x18,
|
||||||
D32_FLOAT_S8X24_UINT = 0x19,
|
Z32_FLOAT_X24S8_UINT = 0x19,
|
||||||
|
/*
|
||||||
|
X8Z24_UNORM_X16V8S8_UINT = 0x1D,
|
||||||
|
Z32_FLOAT_X16V8X8_UINT = 0x1E,
|
||||||
|
Z32_FLOAT_X16V8S8_UINT = 0x1F,
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Engines {
|
namespace Engines {
|
||||||
|
|
|
@ -21,16 +21,16 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||||
|
|
||||||
maxwell3d.regs.draw.topology.Assign(
|
maxwell3d.regs.draw.topology.Assign(
|
||||||
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
|
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
|
||||||
maxwell3d.regs.vb_base_instance = parameters[5];
|
maxwell3d.regs.global_base_instance_index = parameters[5];
|
||||||
maxwell3d.mme_draw.instance_count = instance_count;
|
maxwell3d.mme_draw.instance_count = instance_count;
|
||||||
maxwell3d.regs.vb_element_base = parameters[3];
|
maxwell3d.regs.global_base_vertex_index = parameters[3];
|
||||||
maxwell3d.regs.index_array.count = parameters[1];
|
maxwell3d.regs.index_buffer.count = parameters[1];
|
||||||
maxwell3d.regs.index_array.first = parameters[4];
|
maxwell3d.regs.index_buffer.first = parameters[4];
|
||||||
|
|
||||||
if (maxwell3d.ShouldExecute()) {
|
if (maxwell3d.ShouldExecute()) {
|
||||||
maxwell3d.Rasterizer().Draw(true, true);
|
maxwell3d.Rasterizer().Draw(true, true);
|
||||||
}
|
}
|
||||||
maxwell3d.regs.index_array.count = 0;
|
maxwell3d.regs.index_buffer.count = 0;
|
||||||
maxwell3d.mme_draw.instance_count = 0;
|
maxwell3d.mme_draw.instance_count = 0;
|
||||||
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
|
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||||
|
|
||||||
maxwell3d.regs.vertex_buffer.first = parameters[3];
|
maxwell3d.regs.vertex_buffer.first = parameters[3];
|
||||||
maxwell3d.regs.vertex_buffer.count = parameters[1];
|
maxwell3d.regs.vertex_buffer.count = parameters[1];
|
||||||
maxwell3d.regs.vb_base_instance = parameters[4];
|
maxwell3d.regs.global_base_instance_index = parameters[4];
|
||||||
maxwell3d.regs.draw.topology.Assign(
|
maxwell3d.regs.draw.topology.Assign(
|
||||||
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
|
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
|
||||||
maxwell3d.mme_draw.instance_count = count;
|
maxwell3d.mme_draw.instance_count = count;
|
||||||
|
@ -57,12 +57,12 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||||
const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
|
const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
|
||||||
const u32 element_base = parameters[4];
|
const u32 element_base = parameters[4];
|
||||||
const u32 base_instance = parameters[5];
|
const u32 base_instance = parameters[5];
|
||||||
maxwell3d.regs.index_array.first = parameters[3];
|
maxwell3d.regs.index_buffer.first = parameters[3];
|
||||||
maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
|
maxwell3d.regs.vertex_id_base = element_base;
|
||||||
maxwell3d.regs.index_array.count = parameters[1];
|
maxwell3d.regs.index_buffer.count = parameters[1];
|
||||||
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
maxwell3d.regs.vb_element_base = element_base;
|
maxwell3d.regs.global_base_vertex_index = element_base;
|
||||||
maxwell3d.regs.vb_base_instance = base_instance;
|
maxwell3d.regs.global_base_instance_index = base_instance;
|
||||||
maxwell3d.mme_draw.instance_count = instance_count;
|
maxwell3d.mme_draw.instance_count = instance_count;
|
||||||
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
||||||
maxwell3d.CallMethodFromMME(0x8e4, element_base);
|
maxwell3d.CallMethodFromMME(0x8e4, element_base);
|
||||||
|
@ -72,10 +72,10 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||||
if (maxwell3d.ShouldExecute()) {
|
if (maxwell3d.ShouldExecute()) {
|
||||||
maxwell3d.Rasterizer().Draw(true, true);
|
maxwell3d.Rasterizer().Draw(true, true);
|
||||||
}
|
}
|
||||||
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
|
maxwell3d.regs.vertex_id_base = 0x0;
|
||||||
maxwell3d.regs.index_array.count = 0;
|
maxwell3d.regs.index_buffer.count = 0;
|
||||||
maxwell3d.regs.vb_element_base = 0x0;
|
maxwell3d.regs.global_base_vertex_index = 0x0;
|
||||||
maxwell3d.regs.vb_base_instance = 0x0;
|
maxwell3d.regs.global_base_instance_index = 0x0;
|
||||||
maxwell3d.mme_draw.instance_count = 0;
|
maxwell3d.mme_draw.instance_count = 0;
|
||||||
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
||||||
maxwell3d.CallMethodFromMME(0x8e4, 0x0);
|
maxwell3d.CallMethodFromMME(0x8e4, 0x0);
|
||||||
|
@ -87,10 +87,10 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||||
void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
|
void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
// Clean everything.
|
// Clean everything.
|
||||||
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
|
maxwell3d.regs.vertex_id_base = 0x0;
|
||||||
maxwell3d.regs.index_array.count = 0;
|
maxwell3d.regs.index_buffer.count = 0;
|
||||||
maxwell3d.regs.vb_element_base = 0x0;
|
maxwell3d.regs.global_base_vertex_index = 0x0;
|
||||||
maxwell3d.regs.vb_base_instance = 0x0;
|
maxwell3d.regs.global_base_instance_index = 0x0;
|
||||||
maxwell3d.mme_draw.instance_count = 0;
|
maxwell3d.mme_draw.instance_count = 0;
|
||||||
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
||||||
maxwell3d.CallMethodFromMME(0x8e4, 0x0);
|
maxwell3d.CallMethodFromMME(0x8e4, 0x0);
|
||||||
|
@ -122,11 +122,11 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||||
const u32 first_index = parameters[base + 2];
|
const u32 first_index = parameters[base + 2];
|
||||||
const u32 base_vertex = parameters[base + 3];
|
const u32 base_vertex = parameters[base + 3];
|
||||||
const u32 base_instance = parameters[base + 4];
|
const u32 base_instance = parameters[base + 4];
|
||||||
maxwell3d.regs.index_array.first = first_index;
|
maxwell3d.regs.index_buffer.first = first_index;
|
||||||
maxwell3d.regs.reg_array[0x446] = base_vertex;
|
maxwell3d.regs.vertex_id_base = base_vertex;
|
||||||
maxwell3d.regs.index_array.count = num_vertices;
|
maxwell3d.regs.index_buffer.count = num_vertices;
|
||||||
maxwell3d.regs.vb_element_base = base_vertex;
|
maxwell3d.regs.global_base_vertex_index = base_vertex;
|
||||||
maxwell3d.regs.vb_base_instance = base_instance;
|
maxwell3d.regs.global_base_instance_index = base_instance;
|
||||||
maxwell3d.mme_draw.instance_count = instance_count;
|
maxwell3d.mme_draw.instance_count = instance_count;
|
||||||
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
maxwell3d.CallMethodFromMME(0x8e3, 0x640);
|
||||||
maxwell3d.CallMethodFromMME(0x8e4, base_vertex);
|
maxwell3d.CallMethodFromMME(0x8e4, base_vertex);
|
||||||
|
|
|
@ -137,7 +137,7 @@ public:
|
||||||
std::unique_lock lock{mutex};
|
std::unique_lock lock{mutex};
|
||||||
if (maxwell3d) {
|
if (maxwell3d) {
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
Stream(VideoCore::QueryType::SamplesPassed).Update(regs.samplecnt_enable);
|
Stream(VideoCore::QueryType::SamplesPassed).Update(regs.zpass_pixel_count_enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,8 @@ GLenum AssemblyStage(size_t stage_index) {
|
||||||
/// @param location Hardware location
|
/// @param location Hardware location
|
||||||
/// @return Pair of ARB_transform_feedback3 token stream first and third arguments
|
/// @return Pair of ARB_transform_feedback3 token stream first and third arguments
|
||||||
/// @note Read https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_transform_feedback3.txt
|
/// @note Read https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_transform_feedback3.txt
|
||||||
std::pair<GLint, GLint> TransformFeedbackEnum(u8 location) {
|
std::pair<GLint, GLint> TransformFeedbackEnum(u32 location) {
|
||||||
const u8 index = location / 4;
|
const auto index = location / 4;
|
||||||
if (index >= 8 && index <= 39) {
|
if (index >= 8 && index <= 39) {
|
||||||
return {GL_GENERIC_ATTRIB_NV, index - 8};
|
return {GL_GENERIC_ATTRIB_NV, index - 8};
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||||
buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers);
|
buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers);
|
||||||
|
|
||||||
const auto& regs{maxwell3d->regs};
|
const auto& regs{maxwell3d->regs};
|
||||||
const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
|
const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
|
||||||
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
|
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
|
||||||
const Shader::Info& info{stage_infos[stage]};
|
const Shader::Info& info{stage_infos[stage]};
|
||||||
buffer_cache.UnbindGraphicsStorageBuffers(stage);
|
buffer_cache.UnbindGraphicsStorageBuffers(stage);
|
||||||
|
@ -557,10 +557,25 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||||
++current_stream;
|
++current_stream;
|
||||||
|
|
||||||
const auto& locations = key.xfb_state.varyings[feedback];
|
const auto& locations = key.xfb_state.varyings[feedback];
|
||||||
std::optional<u8> current_index;
|
std::optional<u32> current_index;
|
||||||
for (u32 offset = 0; offset < layout.varying_count; ++offset) {
|
for (u32 offset = 0; offset < layout.varying_count; ++offset) {
|
||||||
const u8 location = locations[offset];
|
const auto get_attribute = [&locations](u32 index) -> u32 {
|
||||||
const u8 index = location / 4;
|
switch (index % 4) {
|
||||||
|
case 0:
|
||||||
|
return locations[index / 4].attribute0.Value();
|
||||||
|
case 1:
|
||||||
|
return locations[index / 4].attribute1.Value();
|
||||||
|
case 2:
|
||||||
|
return locations[index / 4].attribute2.Value();
|
||||||
|
case 3:
|
||||||
|
return locations[index / 4].attribute3.Value();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto attribute{get_attribute(offset)};
|
||||||
|
const auto index = attribute / 4U;
|
||||||
|
|
||||||
if (current_index == index) {
|
if (current_index == index) {
|
||||||
// Increase number of components of the previous attachment
|
// Increase number of components of the previous attachment
|
||||||
|
@ -569,7 +584,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||||
}
|
}
|
||||||
current_index = index;
|
current_index = index;
|
||||||
|
|
||||||
std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(location);
|
std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(attribute);
|
||||||
cursor[1] = 1;
|
cursor[1] = 1;
|
||||||
cursor += XFB_ENTRY_STRIDE;
|
cursor += XFB_ENTRY_STRIDE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ struct GraphicsPipelineKey {
|
||||||
BitField<0, 1, u32> xfb_enabled;
|
BitField<0, 1, u32> xfb_enabled;
|
||||||
BitField<1, 1, u32> early_z;
|
BitField<1, 1, u32> early_z;
|
||||||
BitField<2, 4, Maxwell::PrimitiveTopology> gs_input_topology;
|
BitField<2, 4, Maxwell::PrimitiveTopology> gs_input_topology;
|
||||||
BitField<6, 2, Maxwell::TessellationPrimitive> tessellation_primitive;
|
BitField<6, 2, Maxwell::Tessellation::DomainType> tessellation_primitive;
|
||||||
BitField<8, 2, Maxwell::TessellationSpacing> tessellation_spacing;
|
BitField<8, 2, Maxwell::Tessellation::Spacing> tessellation_spacing;
|
||||||
BitField<10, 1, u32> tessellation_clockwise;
|
BitField<10, 1, u32> tessellation_clockwise;
|
||||||
};
|
};
|
||||||
std::array<u32, 3> padding;
|
std::array<u32, 3> padding;
|
||||||
|
|
|
@ -87,7 +87,7 @@ void RasterizerOpenGL::SyncVertexFormats() {
|
||||||
}
|
}
|
||||||
flags[Dirty::VertexFormat0 + index] = false;
|
flags[Dirty::VertexFormat0 + index] = false;
|
||||||
|
|
||||||
const auto attrib = maxwell3d->regs.vertex_attrib_format[index];
|
const auto& attrib = maxwell3d->regs.vertex_attrib_format[index];
|
||||||
const auto gl_index = static_cast<GLuint>(index);
|
const auto gl_index = static_cast<GLuint>(index);
|
||||||
|
|
||||||
// Disable constant attributes.
|
// Disable constant attributes.
|
||||||
|
@ -97,8 +97,8 @@ void RasterizerOpenGL::SyncVertexFormats() {
|
||||||
}
|
}
|
||||||
glEnableVertexAttribArray(gl_index);
|
glEnableVertexAttribArray(gl_index);
|
||||||
|
|
||||||
if (attrib.type == Maxwell::VertexAttribute::Type::SignedInt ||
|
if (attrib.type == Maxwell::VertexAttribute::Type::SInt ||
|
||||||
attrib.type == Maxwell::VertexAttribute::Type::UnsignedInt) {
|
attrib.type == Maxwell::VertexAttribute::Type::UInt) {
|
||||||
glVertexAttribIFormat(gl_index, attrib.ComponentCount(),
|
glVertexAttribIFormat(gl_index, attrib.ComponentCount(),
|
||||||
MaxwellToGL::VertexFormat(attrib), attrib.offset);
|
MaxwellToGL::VertexFormat(attrib), attrib.offset);
|
||||||
} else {
|
} else {
|
||||||
|
@ -125,8 +125,8 @@ void RasterizerOpenGL::SyncVertexInstances() {
|
||||||
flags[Dirty::VertexInstance0 + index] = false;
|
flags[Dirty::VertexInstance0 + index] = false;
|
||||||
|
|
||||||
const auto gl_index = static_cast<GLuint>(index);
|
const auto gl_index = static_cast<GLuint>(index);
|
||||||
const bool instancing_enabled = regs.instanced_arrays.IsInstancingEnabled(gl_index);
|
const bool instancing_enabled = regs.vertex_stream_instances.IsInstancingEnabled(gl_index);
|
||||||
const GLuint divisor = instancing_enabled ? regs.vertex_array[index].divisor : 0;
|
const GLuint divisor = instancing_enabled ? regs.vertex_streams[index].frequency : 0;
|
||||||
glVertexBindingDivisor(gl_index, divisor);
|
glVertexBindingDivisor(gl_index, divisor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,27 +147,27 @@ void RasterizerOpenGL::Clear() {
|
||||||
bool use_depth{};
|
bool use_depth{};
|
||||||
bool use_stencil{};
|
bool use_stencil{};
|
||||||
|
|
||||||
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
if (regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
|
||||||
regs.clear_buffers.A) {
|
regs.clear_surface.A) {
|
||||||
use_color = true;
|
use_color = true;
|
||||||
|
|
||||||
const GLuint index = regs.clear_buffers.RT;
|
const GLuint index = regs.clear_surface.RT;
|
||||||
state_tracker.NotifyColorMask(index);
|
state_tracker.NotifyColorMask(index);
|
||||||
glColorMaski(index, regs.clear_buffers.R != 0, regs.clear_buffers.G != 0,
|
glColorMaski(index, regs.clear_surface.R != 0, regs.clear_surface.G != 0,
|
||||||
regs.clear_buffers.B != 0, regs.clear_buffers.A != 0);
|
regs.clear_surface.B != 0, regs.clear_surface.A != 0);
|
||||||
|
|
||||||
// TODO(Rodrigo): Determine if clamping is used on clears
|
// TODO(Rodrigo): Determine if clamping is used on clears
|
||||||
SyncFragmentColorClampState();
|
SyncFragmentColorClampState();
|
||||||
SyncFramebufferSRGB();
|
SyncFramebufferSRGB();
|
||||||
}
|
}
|
||||||
if (regs.clear_buffers.Z) {
|
if (regs.clear_surface.Z) {
|
||||||
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
|
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
|
||||||
use_depth = true;
|
use_depth = true;
|
||||||
|
|
||||||
state_tracker.NotifyDepthMask();
|
state_tracker.NotifyDepthMask();
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
}
|
}
|
||||||
if (regs.clear_buffers.S) {
|
if (regs.clear_surface.S) {
|
||||||
ASSERT_MSG(regs.zeta_enable, "Tried to clear stencil but buffer is not enabled!");
|
ASSERT_MSG(regs.zeta_enable, "Tried to clear stencil but buffer is not enabled!");
|
||||||
use_stencil = true;
|
use_stencil = true;
|
||||||
}
|
}
|
||||||
|
@ -184,16 +184,16 @@ void RasterizerOpenGL::Clear() {
|
||||||
texture_cache.UpdateRenderTargets(true);
|
texture_cache.UpdateRenderTargets(true);
|
||||||
state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
|
state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
|
||||||
SyncViewport();
|
SyncViewport();
|
||||||
if (regs.clear_flags.scissor) {
|
if (regs.clear_control.use_scissor) {
|
||||||
SyncScissorTest();
|
SyncScissorTest();
|
||||||
} else {
|
} else {
|
||||||
state_tracker.NotifyScissor0();
|
state_tracker.NotifyScissor0();
|
||||||
glDisablei(GL_SCISSOR_TEST, 0);
|
glDisablei(GL_SCISSOR_TEST, 0);
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_IF(regs.clear_flags.viewport);
|
UNIMPLEMENTED_IF(regs.clear_control.use_viewport_clip0);
|
||||||
|
|
||||||
if (use_color) {
|
if (use_color) {
|
||||||
glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
|
glClearBufferfv(GL_COLOR, regs.clear_surface.RT, regs.clear_color.data());
|
||||||
}
|
}
|
||||||
if (use_depth && use_stencil) {
|
if (use_depth && use_stencil) {
|
||||||
glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
|
glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
|
||||||
|
@ -227,14 +227,14 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
||||||
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
|
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
|
||||||
BeginTransformFeedback(pipeline, primitive_mode);
|
BeginTransformFeedback(pipeline, primitive_mode);
|
||||||
|
|
||||||
const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.vb_base_instance);
|
const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.global_base_instance_index);
|
||||||
const GLsizei num_instances =
|
const GLsizei num_instances =
|
||||||
static_cast<GLsizei>(is_instanced ? maxwell3d->mme_draw.instance_count : 1);
|
static_cast<GLsizei>(is_instanced ? maxwell3d->mme_draw.instance_count : 1);
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.vb_element_base);
|
const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.global_base_vertex_index);
|
||||||
const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_array.count);
|
const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_buffer.count);
|
||||||
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
|
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
|
||||||
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_array.format);
|
const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format);
|
||||||
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
|
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
|
||||||
glDrawElements(primitive_mode, num_vertices, format, offset);
|
glDrawElements(primitive_mode, num_vertices, format, offset);
|
||||||
} else if (num_instances == 1 && base_instance == 0) {
|
} else if (num_instances == 1 && base_instance == 0) {
|
||||||
|
@ -555,9 +555,9 @@ void RasterizerOpenGL::SyncViewport() {
|
||||||
if (dirty_viewport || dirty_clip_control || flags[Dirty::FrontFace]) {
|
if (dirty_viewport || dirty_clip_control || flags[Dirty::FrontFace]) {
|
||||||
flags[Dirty::FrontFace] = false;
|
flags[Dirty::FrontFace] = false;
|
||||||
|
|
||||||
GLenum mode = MaxwellToGL::FrontFace(regs.front_face);
|
GLenum mode = MaxwellToGL::FrontFace(regs.gl_front_face);
|
||||||
bool flip_faces = true;
|
bool flip_faces = true;
|
||||||
if (regs.screen_y_control.triangle_rast_flip != 0) {
|
if (regs.window_origin.flip_y != 0) {
|
||||||
flip_faces = !flip_faces;
|
flip_faces = !flip_faces;
|
||||||
}
|
}
|
||||||
if (regs.viewport_transform[0].scale_y < 0.0f) {
|
if (regs.viewport_transform[0].scale_y < 0.0f) {
|
||||||
|
@ -582,14 +582,15 @@ void RasterizerOpenGL::SyncViewport() {
|
||||||
if (regs.viewport_transform[0].scale_y < 0.0f) {
|
if (regs.viewport_transform[0].scale_y < 0.0f) {
|
||||||
flip_y = !flip_y;
|
flip_y = !flip_y;
|
||||||
}
|
}
|
||||||
if (regs.screen_y_control.y_negate != 0) {
|
const bool lower_left{regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft};
|
||||||
|
if (lower_left) {
|
||||||
flip_y = !flip_y;
|
flip_y = !flip_y;
|
||||||
}
|
}
|
||||||
const bool is_zero_to_one = regs.depth_mode == Maxwell::DepthMode::ZeroToOne;
|
const bool is_zero_to_one = regs.depth_mode == Maxwell::DepthMode::ZeroToOne;
|
||||||
const GLenum origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
|
const GLenum origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;
|
||||||
const GLenum depth = is_zero_to_one ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE;
|
const GLenum depth = is_zero_to_one ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE;
|
||||||
state_tracker.ClipControl(origin, depth);
|
state_tracker.ClipControl(origin, depth);
|
||||||
state_tracker.SetYNegate(regs.screen_y_control.y_negate != 0);
|
state_tracker.SetYNegate(lower_left);
|
||||||
}
|
}
|
||||||
const bool is_rescaling{texture_cache.IsRescaling()};
|
const bool is_rescaling{texture_cache.IsRescaling()};
|
||||||
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
|
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
|
||||||
|
@ -657,7 +658,8 @@ void RasterizerOpenGL::SyncDepthClamp() {
|
||||||
}
|
}
|
||||||
flags[Dirty::DepthClampEnabled] = false;
|
flags[Dirty::DepthClampEnabled] = false;
|
||||||
|
|
||||||
oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.view_volume_clip_control.depth_clamp_disabled == 0);
|
oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.viewport_clip_control.geometry_clip !=
|
||||||
|
Maxwell::ViewportClipControl::GeometryClip::Passthrough);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
|
void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
|
||||||
|
@ -667,7 +669,7 @@ void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
|
||||||
}
|
}
|
||||||
flags[Dirty::ClipDistances] = false;
|
flags[Dirty::ClipDistances] = false;
|
||||||
|
|
||||||
clip_mask &= maxwell3d->regs.clip_distance_enabled;
|
clip_mask &= maxwell3d->regs.user_clip_enable.raw;
|
||||||
if (clip_mask == last_clip_distance_mask) {
|
if (clip_mask == last_clip_distance_mask) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -689,9 +691,9 @@ void RasterizerOpenGL::SyncCullMode() {
|
||||||
if (flags[Dirty::CullTest]) {
|
if (flags[Dirty::CullTest]) {
|
||||||
flags[Dirty::CullTest] = false;
|
flags[Dirty::CullTest] = false;
|
||||||
|
|
||||||
if (regs.cull_test_enabled) {
|
if (regs.gl_cull_test_enabled) {
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(MaxwellToGL::CullFace(regs.cull_face));
|
glCullFace(MaxwellToGL::CullFace(regs.gl_cull_face));
|
||||||
} else {
|
} else {
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
}
|
}
|
||||||
|
@ -743,20 +745,20 @@ void RasterizerOpenGL::SyncStencilTestState() {
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
|
oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
|
||||||
|
|
||||||
glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_func_func),
|
glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_op.func),
|
||||||
regs.stencil_front_func_ref, regs.stencil_front_func_mask);
|
regs.stencil_front_func.ref, regs.stencil_front_func.func_mask);
|
||||||
glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op_fail),
|
glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op.fail),
|
||||||
MaxwellToGL::StencilOp(regs.stencil_front_op_zfail),
|
MaxwellToGL::StencilOp(regs.stencil_front_op.zfail),
|
||||||
MaxwellToGL::StencilOp(regs.stencil_front_op_zpass));
|
MaxwellToGL::StencilOp(regs.stencil_front_op.zpass));
|
||||||
glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
|
glStencilMaskSeparate(GL_FRONT, regs.stencil_front_func.mask);
|
||||||
|
|
||||||
if (regs.stencil_two_side_enable) {
|
if (regs.stencil_two_side_enable) {
|
||||||
glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_func_func),
|
glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_op.func),
|
||||||
regs.stencil_back_func_ref, regs.stencil_back_func_mask);
|
regs.stencil_back_func.ref, regs.stencil_back_func.mask);
|
||||||
glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op_fail),
|
glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op.fail),
|
||||||
MaxwellToGL::StencilOp(regs.stencil_back_op_zfail),
|
MaxwellToGL::StencilOp(regs.stencil_back_op.zfail),
|
||||||
MaxwellToGL::StencilOp(regs.stencil_back_op_zpass));
|
MaxwellToGL::StencilOp(regs.stencil_back_op.zpass));
|
||||||
glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
|
glStencilMaskSeparate(GL_BACK, regs.stencil_back_func.mask);
|
||||||
} else {
|
} else {
|
||||||
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
|
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
|
||||||
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
|
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
@ -782,7 +784,7 @@ void RasterizerOpenGL::SyncPolygonModes() {
|
||||||
flags[Dirty::PolygonModes] = false;
|
flags[Dirty::PolygonModes] = false;
|
||||||
|
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
if (regs.fill_rectangle) {
|
if (regs.fill_via_triangle_mode != Maxwell::FillViaTriangleMode::Disabled) {
|
||||||
if (!GLAD_GL_NV_fill_rectangle) {
|
if (!GLAD_GL_NV_fill_rectangle) {
|
||||||
LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
|
LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
@ -855,8 +857,8 @@ void RasterizerOpenGL::SyncMultiSampleState() {
|
||||||
flags[Dirty::MultisampleControl] = false;
|
flags[Dirty::MultisampleControl] = false;
|
||||||
|
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.multisample_control.alpha_to_coverage);
|
oglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE, regs.anti_alias_alpha_control.alpha_to_coverage);
|
||||||
oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.multisample_control.alpha_to_one);
|
oglEnable(GL_SAMPLE_ALPHA_TO_ONE, regs.anti_alias_alpha_control.alpha_to_one);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncFragmentColorClampState() {
|
void RasterizerOpenGL::SyncFragmentColorClampState() {
|
||||||
|
@ -866,7 +868,8 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {
|
||||||
}
|
}
|
||||||
flags[Dirty::FragmentClampColor] = false;
|
flags[Dirty::FragmentClampColor] = false;
|
||||||
|
|
||||||
glClampColor(GL_CLAMP_FRAGMENT_COLOR, maxwell3d->regs.frag_color_clamp ? GL_TRUE : GL_FALSE);
|
glClampColor(GL_CLAMP_FRAGMENT_COLOR,
|
||||||
|
maxwell3d->regs.frag_color_clamp.AnyEnabled() ? GL_TRUE : GL_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendState() {
|
void RasterizerOpenGL::SyncBlendState() {
|
||||||
|
@ -886,18 +889,18 @@ void RasterizerOpenGL::SyncBlendState() {
|
||||||
}
|
}
|
||||||
flags[Dirty::BlendStates] = false;
|
flags[Dirty::BlendStates] = false;
|
||||||
|
|
||||||
if (!regs.independent_blend_enable) {
|
if (!regs.blend_per_target_enabled) {
|
||||||
if (!regs.blend.enable[0]) {
|
if (!regs.blend.enable[0]) {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb),
|
glBlendFuncSeparate(MaxwellToGL::BlendFunc(regs.blend.color_source),
|
||||||
MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb),
|
MaxwellToGL::BlendFunc(regs.blend.color_dest),
|
||||||
MaxwellToGL::BlendFunc(regs.blend.factor_source_a),
|
MaxwellToGL::BlendFunc(regs.blend.alpha_source),
|
||||||
MaxwellToGL::BlendFunc(regs.blend.factor_dest_a));
|
MaxwellToGL::BlendFunc(regs.blend.alpha_dest));
|
||||||
glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.equation_rgb),
|
glBlendEquationSeparate(MaxwellToGL::BlendEquation(regs.blend.color_op),
|
||||||
MaxwellToGL::BlendEquation(regs.blend.equation_a));
|
MaxwellToGL::BlendEquation(regs.blend.alpha_op));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,14 +919,13 @@ void RasterizerOpenGL::SyncBlendState() {
|
||||||
}
|
}
|
||||||
glEnablei(GL_BLEND, static_cast<GLuint>(i));
|
glEnablei(GL_BLEND, static_cast<GLuint>(i));
|
||||||
|
|
||||||
const auto& src = regs.independent_blend[i];
|
const auto& src = regs.blend_per_target[i];
|
||||||
glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.factor_source_rgb),
|
glBlendFuncSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendFunc(src.color_source),
|
||||||
MaxwellToGL::BlendFunc(src.factor_dest_rgb),
|
MaxwellToGL::BlendFunc(src.color_dest),
|
||||||
MaxwellToGL::BlendFunc(src.factor_source_a),
|
MaxwellToGL::BlendFunc(src.alpha_source),
|
||||||
MaxwellToGL::BlendFunc(src.factor_dest_a));
|
MaxwellToGL::BlendFunc(src.alpha_dest));
|
||||||
glBlendEquationSeparatei(static_cast<GLuint>(i),
|
glBlendEquationSeparatei(static_cast<GLuint>(i), MaxwellToGL::BlendEquation(src.color_op),
|
||||||
MaxwellToGL::BlendEquation(src.equation_rgb),
|
MaxwellToGL::BlendEquation(src.alpha_op));
|
||||||
MaxwellToGL::BlendEquation(src.equation_a));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,7 +939,7 @@ void RasterizerOpenGL::SyncLogicOpState() {
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
if (regs.logic_op.enable) {
|
if (regs.logic_op.enable) {
|
||||||
glEnable(GL_COLOR_LOGIC_OP);
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.operation));
|
glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.op));
|
||||||
} else {
|
} else {
|
||||||
glDisable(GL_COLOR_LOGIC_OP);
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
}
|
}
|
||||||
|
@ -996,7 +998,7 @@ void RasterizerOpenGL::SyncPointState() {
|
||||||
flags[Dirty::PointSize] = false;
|
flags[Dirty::PointSize] = false;
|
||||||
|
|
||||||
oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
|
oglEnable(GL_POINT_SPRITE, maxwell3d->regs.point_sprite_enable);
|
||||||
oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.vp_point_size.enable);
|
oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.point_size_attribute.enabled);
|
||||||
const bool is_rescaling{texture_cache.IsRescaling()};
|
const bool is_rescaling{texture_cache.IsRescaling()};
|
||||||
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
|
const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f;
|
||||||
glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale));
|
glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale));
|
||||||
|
@ -1010,8 +1012,8 @@ void RasterizerOpenGL::SyncLineState() {
|
||||||
flags[Dirty::LineWidth] = false;
|
flags[Dirty::LineWidth] = false;
|
||||||
|
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
oglEnable(GL_LINE_SMOOTH, regs.line_smooth_enable);
|
oglEnable(GL_LINE_SMOOTH, regs.line_anti_alias_enable);
|
||||||
glLineWidth(regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased);
|
glLineWidth(regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncPolygonOffset() {
|
void RasterizerOpenGL::SyncPolygonOffset() {
|
||||||
|
@ -1029,8 +1031,8 @@ void RasterizerOpenGL::SyncPolygonOffset() {
|
||||||
if (regs.polygon_offset_fill_enable || regs.polygon_offset_line_enable ||
|
if (regs.polygon_offset_fill_enable || regs.polygon_offset_line_enable ||
|
||||||
regs.polygon_offset_point_enable) {
|
regs.polygon_offset_point_enable) {
|
||||||
// Hardware divides polygon offset units by two
|
// Hardware divides polygon offset units by two
|
||||||
glPolygonOffsetClamp(regs.polygon_offset_factor, regs.polygon_offset_units / 2.0f,
|
glPolygonOffsetClamp(regs.slope_scale_depth_bias, regs.depth_bias / 2.0f,
|
||||||
regs.polygon_offset_clamp);
|
regs.depth_bias_clamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,14 +1064,14 @@ void RasterizerOpenGL::SyncFramebufferSRGB() {
|
||||||
|
|
||||||
void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
|
void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum primitive_mode) {
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
if (regs.tfb_enabled == 0) {
|
if (regs.transform_feedback_enabled == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
program->ConfigureTransformFeedback();
|
program->ConfigureTransformFeedback();
|
||||||
|
|
||||||
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
|
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
|
||||||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
|
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) ||
|
||||||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
|
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry));
|
||||||
UNIMPLEMENTED_IF(primitive_mode != GL_POINTS);
|
UNIMPLEMENTED_IF(primitive_mode != GL_POINTS);
|
||||||
|
|
||||||
// We may have to call BeginTransformFeedbackNV here since they seem to call different
|
// We may have to call BeginTransformFeedbackNV here since they seem to call different
|
||||||
|
@ -1080,7 +1082,7 @@ void RasterizerOpenGL::BeginTransformFeedback(GraphicsPipeline* program, GLenum
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::EndTransformFeedback() {
|
void RasterizerOpenGL::EndTransformFeedback() {
|
||||||
if (maxwell3d->regs.tfb_enabled != 0) {
|
if (maxwell3d->regs.transform_feedback_enabled != 0) {
|
||||||
glEndTransformFeedback();
|
glEndTransformFeedback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,11 +78,11 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
|
||||||
info.tess_clockwise = key.tessellation_clockwise != 0;
|
info.tess_clockwise = key.tessellation_clockwise != 0;
|
||||||
info.tess_primitive = [&key] {
|
info.tess_primitive = [&key] {
|
||||||
switch (key.tessellation_primitive) {
|
switch (key.tessellation_primitive) {
|
||||||
case Maxwell::TessellationPrimitive::Isolines:
|
case Maxwell::Tessellation::DomainType::Isolines:
|
||||||
return Shader::TessPrimitive::Isolines;
|
return Shader::TessPrimitive::Isolines;
|
||||||
case Maxwell::TessellationPrimitive::Triangles:
|
case Maxwell::Tessellation::DomainType::Triangles:
|
||||||
return Shader::TessPrimitive::Triangles;
|
return Shader::TessPrimitive::Triangles;
|
||||||
case Maxwell::TessellationPrimitive::Quads:
|
case Maxwell::Tessellation::DomainType::Quads:
|
||||||
return Shader::TessPrimitive::Quads;
|
return Shader::TessPrimitive::Quads;
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -90,11 +90,11 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
|
||||||
}();
|
}();
|
||||||
info.tess_spacing = [&] {
|
info.tess_spacing = [&] {
|
||||||
switch (key.tessellation_spacing) {
|
switch (key.tessellation_spacing) {
|
||||||
case Maxwell::TessellationSpacing::Equal:
|
case Maxwell::Tessellation::Spacing::Integer:
|
||||||
return Shader::TessSpacing::Equal;
|
return Shader::TessSpacing::Equal;
|
||||||
case Maxwell::TessellationSpacing::FractionalOdd:
|
case Maxwell::Tessellation::Spacing::FractionalOdd:
|
||||||
return Shader::TessSpacing::FractionalOdd;
|
return Shader::TessSpacing::FractionalOdd;
|
||||||
case Maxwell::TessellationSpacing::FractionalEven:
|
case Maxwell::Tessellation::Spacing::FractionalEven:
|
||||||
return Shader::TessSpacing::FractionalEven;
|
return Shader::TessSpacing::FractionalEven;
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -139,14 +139,15 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
|
void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
|
||||||
std::ranges::transform(regs.tfb_layouts, state.layouts.begin(), [](const auto& layout) {
|
std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(),
|
||||||
|
[](const auto& layout) {
|
||||||
return VideoCommon::TransformFeedbackState::Layout{
|
return VideoCommon::TransformFeedbackState::Layout{
|
||||||
.stream = layout.stream,
|
.stream = layout.stream,
|
||||||
.varying_count = layout.varying_count,
|
.varying_count = layout.varying_count,
|
||||||
.stride = layout.stride,
|
.stride = layout.stride,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
state.varyings = regs.tfb_varying_locs;
|
state.varyings = regs.stream_out_layout;
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
@ -309,14 +310,16 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
|
||||||
}
|
}
|
||||||
const auto& regs{maxwell3d->regs};
|
const auto& regs{maxwell3d->regs};
|
||||||
graphics_key.raw = 0;
|
graphics_key.raw = 0;
|
||||||
graphics_key.early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0);
|
graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
|
||||||
graphics_key.gs_input_topology.Assign(graphics_key.unique_hashes[4] != 0
|
graphics_key.gs_input_topology.Assign(graphics_key.unique_hashes[4] != 0
|
||||||
? regs.draw.topology.Value()
|
? regs.draw.topology.Value()
|
||||||
: Maxwell::PrimitiveTopology{});
|
: Maxwell::PrimitiveTopology{});
|
||||||
graphics_key.tessellation_primitive.Assign(regs.tess_mode.prim.Value());
|
graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value());
|
||||||
graphics_key.tessellation_spacing.Assign(regs.tess_mode.spacing.Value());
|
graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value());
|
||||||
graphics_key.tessellation_clockwise.Assign(regs.tess_mode.cw.Value());
|
graphics_key.tessellation_clockwise.Assign(
|
||||||
graphics_key.xfb_enabled.Assign(regs.tfb_enabled != 0 ? 1 : 0);
|
regs.tessellation.params.output_primitives.Value() !=
|
||||||
|
Maxwell::Tessellation::OutputPrimitves::Triangles_CCW);
|
||||||
|
graphics_key.xfb_enabled.Assign(regs.transform_feedback_enabled != 0 ? 1 : 0);
|
||||||
if (graphics_key.xfb_enabled) {
|
if (graphics_key.xfb_enabled) {
|
||||||
SetXfbState(graphics_key.xfb_state, regs);
|
SetXfbState(graphics_key.xfb_state, regs);
|
||||||
}
|
}
|
||||||
|
@ -354,7 +357,7 @@ GraphicsPipeline* ShaderCache::BuiltPipeline(GraphicsPipeline* pipeline) const n
|
||||||
// If games are using a small index count, we can assume these are full screen quads.
|
// If games are using a small index count, we can assume these are full screen quads.
|
||||||
// Usually these shaders are only used once for building textures so we can assume they
|
// Usually these shaders are only used once for building textures so we can assume they
|
||||||
// can't be built async
|
// can't be built async
|
||||||
if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
|
if (maxwell3d->regs.index_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -38,12 +38,12 @@ void SetupDirtyColorMasks(Tables& tables) {
|
||||||
void SetupDirtyVertexInstances(Tables& tables) {
|
void SetupDirtyVertexInstances(Tables& tables) {
|
||||||
static constexpr std::size_t instance_base_offset = 3;
|
static constexpr std::size_t instance_base_offset = 3;
|
||||||
for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) {
|
for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) {
|
||||||
const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[0]);
|
const std::size_t array_offset = OFF(vertex_streams) + i * NUM(vertex_streams[0]);
|
||||||
const std::size_t instance_array_offset = array_offset + instance_base_offset;
|
const std::size_t instance_array_offset = array_offset + instance_base_offset;
|
||||||
tables[0][instance_array_offset] = static_cast<u8>(VertexInstance0 + i);
|
tables[0][instance_array_offset] = static_cast<u8>(VertexInstance0 + i);
|
||||||
tables[1][instance_array_offset] = VertexInstances;
|
tables[1][instance_array_offset] = VertexInstances;
|
||||||
|
|
||||||
const std::size_t instance_offset = OFF(instanced_arrays) + i;
|
const std::size_t instance_offset = OFF(vertex_stream_instances) + i;
|
||||||
tables[0][instance_offset] = static_cast<u8>(VertexInstance0 + i);
|
tables[0][instance_offset] = static_cast<u8>(VertexInstance0 + i);
|
||||||
tables[1][instance_offset] = VertexInstances;
|
tables[1][instance_offset] = VertexInstances;
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,8 @@ void SetupDirtyViewports(Tables& tables) {
|
||||||
FillBlock(tables[1], OFF(viewport_transform), NUM(viewport_transform), Viewports);
|
FillBlock(tables[1], OFF(viewport_transform), NUM(viewport_transform), Viewports);
|
||||||
FillBlock(tables[1], OFF(viewports), NUM(viewports), Viewports);
|
FillBlock(tables[1], OFF(viewports), NUM(viewports), Viewports);
|
||||||
|
|
||||||
tables[0][OFF(viewport_transform_enabled)] = ViewportTransform;
|
tables[0][OFF(viewport_scale_offset_enbled)] = ViewportTransform;
|
||||||
tables[1][OFF(viewport_transform_enabled)] = Viewports;
|
tables[1][OFF(viewport_scale_offset_enbled)] = Viewports;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyScissors(Tables& tables) {
|
void SetupDirtyScissors(Tables& tables) {
|
||||||
|
@ -88,7 +88,7 @@ void SetupDirtyPolygonModes(Tables& tables) {
|
||||||
|
|
||||||
tables[1][OFF(polygon_mode_front)] = PolygonModes;
|
tables[1][OFF(polygon_mode_front)] = PolygonModes;
|
||||||
tables[1][OFF(polygon_mode_back)] = PolygonModes;
|
tables[1][OFF(polygon_mode_back)] = PolygonModes;
|
||||||
tables[0][OFF(fill_rectangle)] = PolygonModes;
|
tables[0][OFF(fill_via_triangle_mode)] = PolygonModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyDepthTest(Tables& tables) {
|
void SetupDirtyDepthTest(Tables& tables) {
|
||||||
|
@ -100,12 +100,14 @@ void SetupDirtyDepthTest(Tables& tables) {
|
||||||
|
|
||||||
void SetupDirtyStencilTest(Tables& tables) {
|
void SetupDirtyStencilTest(Tables& tables) {
|
||||||
static constexpr std::array offsets = {
|
static constexpr std::array offsets = {
|
||||||
OFF(stencil_enable), OFF(stencil_front_func_func), OFF(stencil_front_func_ref),
|
OFF(stencil_enable), OFF(stencil_front_op.func),
|
||||||
OFF(stencil_front_func_mask), OFF(stencil_front_op_fail), OFF(stencil_front_op_zfail),
|
OFF(stencil_front_func.ref), OFF(stencil_front_func.func_mask),
|
||||||
OFF(stencil_front_op_zpass), OFF(stencil_front_mask), OFF(stencil_two_side_enable),
|
OFF(stencil_front_op.fail), OFF(stencil_front_op.zfail),
|
||||||
OFF(stencil_back_func_func), OFF(stencil_back_func_ref), OFF(stencil_back_func_mask),
|
OFF(stencil_front_op.zpass), OFF(stencil_front_func.mask),
|
||||||
OFF(stencil_back_op_fail), OFF(stencil_back_op_zfail), OFF(stencil_back_op_zpass),
|
OFF(stencil_two_side_enable), OFF(stencil_back_op.func),
|
||||||
OFF(stencil_back_mask)};
|
OFF(stencil_back_func.ref), OFF(stencil_back_func.func_mask),
|
||||||
|
OFF(stencil_back_op.fail), OFF(stencil_back_op.zfail),
|
||||||
|
OFF(stencil_back_op.zpass), OFF(stencil_back_func.mask)};
|
||||||
for (const auto offset : offsets) {
|
for (const auto offset : offsets) {
|
||||||
tables[0][offset] = StencilTest;
|
tables[0][offset] = StencilTest;
|
||||||
}
|
}
|
||||||
|
@ -121,15 +123,15 @@ void SetupDirtyAlphaTest(Tables& tables) {
|
||||||
void SetupDirtyBlend(Tables& tables) {
|
void SetupDirtyBlend(Tables& tables) {
|
||||||
FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendColor);
|
FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendColor);
|
||||||
|
|
||||||
tables[0][OFF(independent_blend_enable)] = BlendIndependentEnabled;
|
tables[0][OFF(blend_per_target_enabled)] = BlendIndependentEnabled;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < Regs::NumRenderTargets; ++i) {
|
for (std::size_t i = 0; i < Regs::NumRenderTargets; ++i) {
|
||||||
const std::size_t offset = OFF(independent_blend) + i * NUM(independent_blend[0]);
|
const std::size_t offset = OFF(blend_per_target) + i * NUM(blend_per_target[0]);
|
||||||
FillBlock(tables[0], offset, NUM(independent_blend[0]), BlendState0 + i);
|
FillBlock(tables[0], offset, NUM(blend_per_target[0]), BlendState0 + i);
|
||||||
|
|
||||||
tables[0][OFF(blend.enable) + i] = static_cast<u8>(BlendState0 + i);
|
tables[0][OFF(blend.enable) + i] = static_cast<u8>(BlendState0 + i);
|
||||||
}
|
}
|
||||||
FillBlock(tables[1], OFF(independent_blend), NUM(independent_blend), BlendStates);
|
FillBlock(tables[1], OFF(blend_per_target), NUM(blend_per_target), BlendStates);
|
||||||
FillBlock(tables[1], OFF(blend), NUM(blend), BlendStates);
|
FillBlock(tables[1], OFF(blend), NUM(blend), BlendStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,13 +144,14 @@ void SetupDirtyPolygonOffset(Tables& tables) {
|
||||||
table[OFF(polygon_offset_fill_enable)] = PolygonOffset;
|
table[OFF(polygon_offset_fill_enable)] = PolygonOffset;
|
||||||
table[OFF(polygon_offset_line_enable)] = PolygonOffset;
|
table[OFF(polygon_offset_line_enable)] = PolygonOffset;
|
||||||
table[OFF(polygon_offset_point_enable)] = PolygonOffset;
|
table[OFF(polygon_offset_point_enable)] = PolygonOffset;
|
||||||
table[OFF(polygon_offset_factor)] = PolygonOffset;
|
table[OFF(slope_scale_depth_bias)] = PolygonOffset;
|
||||||
table[OFF(polygon_offset_units)] = PolygonOffset;
|
table[OFF(depth_bias)] = PolygonOffset;
|
||||||
table[OFF(polygon_offset_clamp)] = PolygonOffset;
|
table[OFF(depth_bias_clamp)] = PolygonOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyMultisampleControl(Tables& tables) {
|
void SetupDirtyMultisampleControl(Tables& tables) {
|
||||||
FillBlock(tables[0], OFF(multisample_control), NUM(multisample_control), MultisampleControl);
|
FillBlock(tables[0], OFF(anti_alias_alpha_control), NUM(anti_alias_alpha_control),
|
||||||
|
MultisampleControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyRasterizeEnable(Tables& tables) {
|
void SetupDirtyRasterizeEnable(Tables& tables) {
|
||||||
|
@ -168,7 +171,7 @@ void SetupDirtyFragmentClampColor(Tables& tables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyPointSize(Tables& tables) {
|
void SetupDirtyPointSize(Tables& tables) {
|
||||||
tables[0][OFF(vp_point_size)] = PointSize;
|
tables[0][OFF(point_size_attribute)] = PointSize;
|
||||||
tables[0][OFF(point_size)] = PointSize;
|
tables[0][OFF(point_size)] = PointSize;
|
||||||
tables[0][OFF(point_sprite_enable)] = PointSize;
|
tables[0][OFF(point_sprite_enable)] = PointSize;
|
||||||
}
|
}
|
||||||
|
@ -176,28 +179,28 @@ void SetupDirtyPointSize(Tables& tables) {
|
||||||
void SetupDirtyLineWidth(Tables& tables) {
|
void SetupDirtyLineWidth(Tables& tables) {
|
||||||
tables[0][OFF(line_width_smooth)] = LineWidth;
|
tables[0][OFF(line_width_smooth)] = LineWidth;
|
||||||
tables[0][OFF(line_width_aliased)] = LineWidth;
|
tables[0][OFF(line_width_aliased)] = LineWidth;
|
||||||
tables[0][OFF(line_smooth_enable)] = LineWidth;
|
tables[0][OFF(line_anti_alias_enable)] = LineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyClipControl(Tables& tables) {
|
void SetupDirtyClipControl(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
table[OFF(screen_y_control)] = ClipControl;
|
table[OFF(window_origin)] = ClipControl;
|
||||||
table[OFF(depth_mode)] = ClipControl;
|
table[OFF(depth_mode)] = ClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyDepthClampEnabled(Tables& tables) {
|
void SetupDirtyDepthClampEnabled(Tables& tables) {
|
||||||
tables[0][OFF(view_volume_clip_control)] = DepthClampEnabled;
|
tables[0][OFF(viewport_clip_control)] = DepthClampEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyMisc(Tables& tables) {
|
void SetupDirtyMisc(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
|
|
||||||
table[OFF(clip_distance_enabled)] = ClipDistances;
|
table[OFF(user_clip_enable)] = ClipDistances;
|
||||||
|
|
||||||
table[OFF(front_face)] = FrontFace;
|
table[OFF(gl_front_face)] = FrontFace;
|
||||||
|
|
||||||
table[OFF(cull_test_enabled)] = CullTest;
|
table[OFF(gl_cull_test_enabled)] = CullTest;
|
||||||
table[OFF(cull_face)] = CullTest;
|
table[OFF(gl_cull_face)] = CullTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
|
@ -126,51 +126,60 @@ inline const FormatTuple& GetFormatTuple(VideoCore::Surface::PixelFormat pixel_f
|
||||||
|
|
||||||
inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
|
inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
|
||||||
switch (attrib.type) {
|
switch (attrib.type) {
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedNorm:
|
case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedScaled:
|
ASSERT_MSG(false, "Invalid vertex attribute type!");
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedInt:
|
break;
|
||||||
|
case Maxwell::VertexAttribute::Type::UNorm:
|
||||||
|
case Maxwell::VertexAttribute::Type::UScaled:
|
||||||
|
case Maxwell::VertexAttribute::Type::UInt:
|
||||||
switch (attrib.size) {
|
switch (attrib.size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return GL_UNSIGNED_BYTE;
|
return GL_UNSIGNED_BYTE;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return GL_UNSIGNED_SHORT;
|
return GL_UNSIGNED_SHORT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32:
|
case Maxwell::VertexAttribute::Size::Size_R32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
|
||||||
return GL_UNSIGNED_INT;
|
return GL_UNSIGNED_INT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return GL_UNSIGNED_INT_2_10_10_10_REV;
|
return GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::SignedNorm:
|
case Maxwell::VertexAttribute::Type::SNorm:
|
||||||
case Maxwell::VertexAttribute::Type::SignedScaled:
|
case Maxwell::VertexAttribute::Type::SScaled:
|
||||||
case Maxwell::VertexAttribute::Type::SignedInt:
|
case Maxwell::VertexAttribute::Type::SInt:
|
||||||
switch (attrib.size) {
|
switch (attrib.size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return GL_BYTE;
|
return GL_BYTE;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return GL_SHORT;
|
return GL_SHORT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32:
|
case Maxwell::VertexAttribute::Size::Size_R32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
|
||||||
return GL_INT;
|
return GL_INT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return GL_INT_2_10_10_10_REV;
|
return GL_INT_2_10_10_10_REV;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -178,17 +187,17 @@ inline GLenum VertexFormat(Maxwell::VertexAttribute attrib) {
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::Float:
|
case Maxwell::VertexAttribute::Type::Float:
|
||||||
switch (attrib.size) {
|
switch (attrib.size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return GL_HALF_FLOAT;
|
return GL_HALF_FLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32:
|
case Maxwell::VertexAttribute::Size::Size_R32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
|
||||||
return GL_FLOAT;
|
return GL_FLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_11_11_10:
|
case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
|
||||||
return GL_UNSIGNED_INT_10F_11F_11F_REV;
|
return GL_UNSIGNED_INT_10F_11F_11F_REV;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -335,20 +344,20 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
|
||||||
|
|
||||||
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
||||||
switch (equation) {
|
switch (equation) {
|
||||||
case Maxwell::Blend::Equation::Add:
|
case Maxwell::Blend::Equation::Add_D3D:
|
||||||
case Maxwell::Blend::Equation::AddGL:
|
case Maxwell::Blend::Equation::Add_GL:
|
||||||
return GL_FUNC_ADD;
|
return GL_FUNC_ADD;
|
||||||
case Maxwell::Blend::Equation::Subtract:
|
case Maxwell::Blend::Equation::Subtract_D3D:
|
||||||
case Maxwell::Blend::Equation::SubtractGL:
|
case Maxwell::Blend::Equation::Subtract_GL:
|
||||||
return GL_FUNC_SUBTRACT;
|
return GL_FUNC_SUBTRACT;
|
||||||
case Maxwell::Blend::Equation::ReverseSubtract:
|
case Maxwell::Blend::Equation::ReverseSubtract_D3D:
|
||||||
case Maxwell::Blend::Equation::ReverseSubtractGL:
|
case Maxwell::Blend::Equation::ReverseSubtract_GL:
|
||||||
return GL_FUNC_REVERSE_SUBTRACT;
|
return GL_FUNC_REVERSE_SUBTRACT;
|
||||||
case Maxwell::Blend::Equation::Min:
|
case Maxwell::Blend::Equation::Min_D3D:
|
||||||
case Maxwell::Blend::Equation::MinGL:
|
case Maxwell::Blend::Equation::Min_GL:
|
||||||
return GL_MIN;
|
return GL_MIN;
|
||||||
case Maxwell::Blend::Equation::Max:
|
case Maxwell::Blend::Equation::Max_D3D:
|
||||||
case Maxwell::Blend::Equation::MaxGL:
|
case Maxwell::Blend::Equation::Max_GL:
|
||||||
return GL_MAX;
|
return GL_MAX;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
|
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
|
||||||
|
@ -357,62 +366,62 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
||||||
|
|
||||||
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
||||||
switch (factor) {
|
switch (factor) {
|
||||||
case Maxwell::Blend::Factor::Zero:
|
case Maxwell::Blend::Factor::Zero_D3D:
|
||||||
case Maxwell::Blend::Factor::ZeroGL:
|
case Maxwell::Blend::Factor::Zero_GL:
|
||||||
return GL_ZERO;
|
return GL_ZERO;
|
||||||
case Maxwell::Blend::Factor::One:
|
case Maxwell::Blend::Factor::One_D3D:
|
||||||
case Maxwell::Blend::Factor::OneGL:
|
case Maxwell::Blend::Factor::One_GL:
|
||||||
return GL_ONE;
|
return GL_ONE;
|
||||||
case Maxwell::Blend::Factor::SourceColor:
|
case Maxwell::Blend::Factor::SourceColor_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceColorGL:
|
case Maxwell::Blend::Factor::SourceColor_GL:
|
||||||
return GL_SRC_COLOR;
|
return GL_SRC_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceColor:
|
case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceColorGL:
|
case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
|
||||||
return GL_ONE_MINUS_SRC_COLOR;
|
return GL_ONE_MINUS_SRC_COLOR;
|
||||||
case Maxwell::Blend::Factor::SourceAlpha:
|
case Maxwell::Blend::Factor::SourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceAlphaGL:
|
case Maxwell::Blend::Factor::SourceAlpha_GL:
|
||||||
return GL_SRC_ALPHA;
|
return GL_SRC_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
|
case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
|
||||||
return GL_ONE_MINUS_SRC_ALPHA;
|
return GL_ONE_MINUS_SRC_ALPHA;
|
||||||
case Maxwell::Blend::Factor::DestAlpha:
|
case Maxwell::Blend::Factor::DestAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::DestAlphaGL:
|
case Maxwell::Blend::Factor::DestAlpha_GL:
|
||||||
return GL_DST_ALPHA;
|
return GL_DST_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusDestAlpha:
|
case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
|
||||||
return GL_ONE_MINUS_DST_ALPHA;
|
return GL_ONE_MINUS_DST_ALPHA;
|
||||||
case Maxwell::Blend::Factor::DestColor:
|
case Maxwell::Blend::Factor::DestColor_D3D:
|
||||||
case Maxwell::Blend::Factor::DestColorGL:
|
case Maxwell::Blend::Factor::DestColor_GL:
|
||||||
return GL_DST_COLOR;
|
return GL_DST_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusDestColor:
|
case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusDestColorGL:
|
case Maxwell::Blend::Factor::OneMinusDestColor_GL:
|
||||||
return GL_ONE_MINUS_DST_COLOR;
|
return GL_ONE_MINUS_DST_COLOR;
|
||||||
case Maxwell::Blend::Factor::SourceAlphaSaturate:
|
case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
|
case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
|
||||||
return GL_SRC_ALPHA_SATURATE;
|
return GL_SRC_ALPHA_SATURATE;
|
||||||
case Maxwell::Blend::Factor::Source1Color:
|
case Maxwell::Blend::Factor::Source1Color_D3D:
|
||||||
case Maxwell::Blend::Factor::Source1ColorGL:
|
case Maxwell::Blend::Factor::Source1Color_GL:
|
||||||
return GL_SRC1_COLOR;
|
return GL_SRC1_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1Color:
|
case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
|
case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
|
||||||
return GL_ONE_MINUS_SRC1_COLOR;
|
return GL_ONE_MINUS_SRC1_COLOR;
|
||||||
case Maxwell::Blend::Factor::Source1Alpha:
|
case Maxwell::Blend::Factor::Source1Alpha_D3D:
|
||||||
case Maxwell::Blend::Factor::Source1AlphaGL:
|
case Maxwell::Blend::Factor::Source1Alpha_GL:
|
||||||
return GL_SRC1_ALPHA;
|
return GL_SRC1_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
|
case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
|
case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
|
||||||
return GL_ONE_MINUS_SRC1_ALPHA;
|
return GL_ONE_MINUS_SRC1_ALPHA;
|
||||||
case Maxwell::Blend::Factor::ConstantColor:
|
case Maxwell::Blend::Factor::BlendFactor_D3D:
|
||||||
case Maxwell::Blend::Factor::ConstantColorGL:
|
case Maxwell::Blend::Factor::ConstantColor_GL:
|
||||||
return GL_CONSTANT_COLOR;
|
return GL_CONSTANT_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantColor:
|
case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantColorGL:
|
case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
|
||||||
return GL_ONE_MINUS_CONSTANT_COLOR;
|
return GL_ONE_MINUS_CONSTANT_COLOR;
|
||||||
case Maxwell::Blend::Factor::ConstantAlpha:
|
case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::ConstantAlphaGL:
|
case Maxwell::Blend::Factor::ConstantAlpha_GL:
|
||||||
return GL_CONSTANT_ALPHA;
|
return GL_CONSTANT_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
|
case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
|
||||||
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
|
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
|
||||||
|
@ -421,60 +430,60 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
||||||
|
|
||||||
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Maxwell::ComparisonOp::Never:
|
case Maxwell::ComparisonOp::Never_D3D:
|
||||||
case Maxwell::ComparisonOp::NeverOld:
|
case Maxwell::ComparisonOp::Never_GL:
|
||||||
return GL_NEVER;
|
return GL_NEVER;
|
||||||
case Maxwell::ComparisonOp::Less:
|
case Maxwell::ComparisonOp::Less_D3D:
|
||||||
case Maxwell::ComparisonOp::LessOld:
|
case Maxwell::ComparisonOp::Less_GL:
|
||||||
return GL_LESS;
|
return GL_LESS;
|
||||||
case Maxwell::ComparisonOp::Equal:
|
case Maxwell::ComparisonOp::Equal_D3D:
|
||||||
case Maxwell::ComparisonOp::EqualOld:
|
case Maxwell::ComparisonOp::Equal_GL:
|
||||||
return GL_EQUAL;
|
return GL_EQUAL;
|
||||||
case Maxwell::ComparisonOp::LessEqual:
|
case Maxwell::ComparisonOp::LessEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::LessEqualOld:
|
case Maxwell::ComparisonOp::LessEqual_GL:
|
||||||
return GL_LEQUAL;
|
return GL_LEQUAL;
|
||||||
case Maxwell::ComparisonOp::Greater:
|
case Maxwell::ComparisonOp::Greater_D3D:
|
||||||
case Maxwell::ComparisonOp::GreaterOld:
|
case Maxwell::ComparisonOp::Greater_GL:
|
||||||
return GL_GREATER;
|
return GL_GREATER;
|
||||||
case Maxwell::ComparisonOp::NotEqual:
|
case Maxwell::ComparisonOp::NotEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::NotEqualOld:
|
case Maxwell::ComparisonOp::NotEqual_GL:
|
||||||
return GL_NOTEQUAL;
|
return GL_NOTEQUAL;
|
||||||
case Maxwell::ComparisonOp::GreaterEqual:
|
case Maxwell::ComparisonOp::GreaterEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::GreaterEqualOld:
|
case Maxwell::ComparisonOp::GreaterEqual_GL:
|
||||||
return GL_GEQUAL;
|
return GL_GEQUAL;
|
||||||
case Maxwell::ComparisonOp::Always:
|
case Maxwell::ComparisonOp::Always_D3D:
|
||||||
case Maxwell::ComparisonOp::AlwaysOld:
|
case Maxwell::ComparisonOp::Always_GL:
|
||||||
return GL_ALWAYS;
|
return GL_ALWAYS;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
|
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
|
||||||
return GL_ALWAYS;
|
return GL_ALWAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum StencilOp(Maxwell::StencilOp stencil) {
|
inline GLenum StencilOp(Maxwell::StencilOp::Op stencil) {
|
||||||
switch (stencil) {
|
switch (stencil) {
|
||||||
case Maxwell::StencilOp::Keep:
|
case Maxwell::StencilOp::Op::Keep_D3D:
|
||||||
case Maxwell::StencilOp::KeepOGL:
|
case Maxwell::StencilOp::Op::Keep_GL:
|
||||||
return GL_KEEP;
|
return GL_KEEP;
|
||||||
case Maxwell::StencilOp::Zero:
|
case Maxwell::StencilOp::Op::Zero_D3D:
|
||||||
case Maxwell::StencilOp::ZeroOGL:
|
case Maxwell::StencilOp::Op::Zero_GL:
|
||||||
return GL_ZERO;
|
return GL_ZERO;
|
||||||
case Maxwell::StencilOp::Replace:
|
case Maxwell::StencilOp::Op::Replace_D3D:
|
||||||
case Maxwell::StencilOp::ReplaceOGL:
|
case Maxwell::StencilOp::Op::Replace_GL:
|
||||||
return GL_REPLACE;
|
return GL_REPLACE;
|
||||||
case Maxwell::StencilOp::Incr:
|
case Maxwell::StencilOp::Op::IncrSaturate_D3D:
|
||||||
case Maxwell::StencilOp::IncrOGL:
|
case Maxwell::StencilOp::Op::IncrSaturate_GL:
|
||||||
return GL_INCR;
|
return GL_INCR;
|
||||||
case Maxwell::StencilOp::Decr:
|
case Maxwell::StencilOp::Op::DecrSaturate_D3D:
|
||||||
case Maxwell::StencilOp::DecrOGL:
|
case Maxwell::StencilOp::Op::DecrSaturate_GL:
|
||||||
return GL_DECR;
|
return GL_DECR;
|
||||||
case Maxwell::StencilOp::Invert:
|
case Maxwell::StencilOp::Op::Invert_D3D:
|
||||||
case Maxwell::StencilOp::InvertOGL:
|
case Maxwell::StencilOp::Op::Invert_GL:
|
||||||
return GL_INVERT;
|
return GL_INVERT;
|
||||||
case Maxwell::StencilOp::IncrWrap:
|
case Maxwell::StencilOp::Op::Incr_D3D:
|
||||||
case Maxwell::StencilOp::IncrWrapOGL:
|
case Maxwell::StencilOp::Op::Incr_GL:
|
||||||
return GL_INCR_WRAP;
|
return GL_INCR_WRAP;
|
||||||
case Maxwell::StencilOp::DecrWrap:
|
case Maxwell::StencilOp::Op::Decr_D3D:
|
||||||
case Maxwell::StencilOp::DecrWrapOGL:
|
case Maxwell::StencilOp::Op::Decr_GL:
|
||||||
return GL_DECR_WRAP;
|
return GL_DECR_WRAP;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil);
|
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil);
|
||||||
|
@ -505,39 +514,39 @@ inline GLenum CullFace(Maxwell::CullFace cull_face) {
|
||||||
return GL_BACK;
|
return GL_BACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum LogicOp(Maxwell::LogicOperation operation) {
|
inline GLenum LogicOp(Maxwell::LogicOp::Op operation) {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case Maxwell::LogicOperation::Clear:
|
case Maxwell::LogicOp::Op::Clear:
|
||||||
return GL_CLEAR;
|
return GL_CLEAR;
|
||||||
case Maxwell::LogicOperation::And:
|
case Maxwell::LogicOp::Op::And:
|
||||||
return GL_AND;
|
return GL_AND;
|
||||||
case Maxwell::LogicOperation::AndReverse:
|
case Maxwell::LogicOp::Op::AndReverse:
|
||||||
return GL_AND_REVERSE;
|
return GL_AND_REVERSE;
|
||||||
case Maxwell::LogicOperation::Copy:
|
case Maxwell::LogicOp::Op::Copy:
|
||||||
return GL_COPY;
|
return GL_COPY;
|
||||||
case Maxwell::LogicOperation::AndInverted:
|
case Maxwell::LogicOp::Op::AndInverted:
|
||||||
return GL_AND_INVERTED;
|
return GL_AND_INVERTED;
|
||||||
case Maxwell::LogicOperation::NoOp:
|
case Maxwell::LogicOp::Op::NoOp:
|
||||||
return GL_NOOP;
|
return GL_NOOP;
|
||||||
case Maxwell::LogicOperation::Xor:
|
case Maxwell::LogicOp::Op::Xor:
|
||||||
return GL_XOR;
|
return GL_XOR;
|
||||||
case Maxwell::LogicOperation::Or:
|
case Maxwell::LogicOp::Op::Or:
|
||||||
return GL_OR;
|
return GL_OR;
|
||||||
case Maxwell::LogicOperation::Nor:
|
case Maxwell::LogicOp::Op::Nor:
|
||||||
return GL_NOR;
|
return GL_NOR;
|
||||||
case Maxwell::LogicOperation::Equiv:
|
case Maxwell::LogicOp::Op::Equiv:
|
||||||
return GL_EQUIV;
|
return GL_EQUIV;
|
||||||
case Maxwell::LogicOperation::Invert:
|
case Maxwell::LogicOp::Op::Invert:
|
||||||
return GL_INVERT;
|
return GL_INVERT;
|
||||||
case Maxwell::LogicOperation::OrReverse:
|
case Maxwell::LogicOp::Op::OrReverse:
|
||||||
return GL_OR_REVERSE;
|
return GL_OR_REVERSE;
|
||||||
case Maxwell::LogicOperation::CopyInverted:
|
case Maxwell::LogicOp::Op::CopyInverted:
|
||||||
return GL_COPY_INVERTED;
|
return GL_COPY_INVERTED;
|
||||||
case Maxwell::LogicOperation::OrInverted:
|
case Maxwell::LogicOp::Op::OrInverted:
|
||||||
return GL_OR_INVERTED;
|
return GL_OR_INVERTED;
|
||||||
case Maxwell::LogicOperation::Nand:
|
case Maxwell::LogicOp::Op::Nand:
|
||||||
return GL_NAND;
|
return GL_NAND;
|
||||||
case Maxwell::LogicOperation::Set:
|
case Maxwell::LogicOp::Op::Set:
|
||||||
return GL_SET;
|
return GL_SET;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented logic operation={}", operation);
|
UNIMPLEMENTED_MSG("Unimplemented logic operation={}", operation);
|
||||||
|
|
|
@ -34,14 +34,15 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
|
||||||
};
|
};
|
||||||
|
|
||||||
void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
|
void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) {
|
||||||
std::ranges::transform(regs.tfb_layouts, state.layouts.begin(), [](const auto& layout) {
|
std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(),
|
||||||
|
[](const auto& layout) {
|
||||||
return VideoCommon::TransformFeedbackState::Layout{
|
return VideoCommon::TransformFeedbackState::Layout{
|
||||||
.stream = layout.stream,
|
.stream = layout.stream,
|
||||||
.varying_count = layout.varying_count,
|
.varying_count = layout.varying_count,
|
||||||
.stride = layout.stride,
|
.stride = layout.stride,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
state.varyings = regs.tfb_varying_locs;
|
state.varyings = regs.stream_out_layout;
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
@ -58,33 +59,34 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
|
||||||
raw1 = 0;
|
raw1 = 0;
|
||||||
extended_dynamic_state.Assign(has_extended_dynamic_state ? 1 : 0);
|
extended_dynamic_state.Assign(has_extended_dynamic_state ? 1 : 0);
|
||||||
dynamic_vertex_input.Assign(has_dynamic_vertex_input ? 1 : 0);
|
dynamic_vertex_input.Assign(has_dynamic_vertex_input ? 1 : 0);
|
||||||
xfb_enabled.Assign(regs.tfb_enabled != 0);
|
xfb_enabled.Assign(regs.transform_feedback_enabled != 0);
|
||||||
primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
|
primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
|
||||||
depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
|
depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
|
||||||
depth_clamp_disabled.Assign(regs.view_volume_clip_control.depth_clamp_disabled.Value());
|
depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
|
||||||
|
Maxwell::ViewportClipControl::GeometryClip::Passthrough);
|
||||||
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
|
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
|
||||||
polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front));
|
polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front));
|
||||||
patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
|
patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
|
||||||
tessellation_primitive.Assign(static_cast<u32>(regs.tess_mode.prim.Value()));
|
tessellation_primitive.Assign(static_cast<u32>(regs.tessellation.params.domain_type.Value()));
|
||||||
tessellation_spacing.Assign(static_cast<u32>(regs.tess_mode.spacing.Value()));
|
tessellation_spacing.Assign(static_cast<u32>(regs.tessellation.params.spacing.Value()));
|
||||||
tessellation_clockwise.Assign(regs.tess_mode.cw.Value());
|
tessellation_clockwise.Assign(regs.tessellation.params.output_primitives.Value() !=
|
||||||
|
Maxwell::Tessellation::OutputPrimitves::Triangles_CCW);
|
||||||
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
||||||
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
|
logic_op.Assign(PackLogicOp(regs.logic_op.op));
|
||||||
topology.Assign(regs.draw.topology);
|
topology.Assign(regs.draw.topology);
|
||||||
msaa_mode.Assign(regs.multisample_mode);
|
msaa_mode.Assign(regs.anti_alias_samples_mode);
|
||||||
|
|
||||||
raw2 = 0;
|
raw2 = 0;
|
||||||
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
|
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
|
||||||
const auto test_func =
|
const auto test_func =
|
||||||
regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always;
|
regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always_GL;
|
||||||
alpha_test_func.Assign(PackComparisonOp(test_func));
|
alpha_test_func.Assign(PackComparisonOp(test_func));
|
||||||
early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0);
|
early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
|
||||||
depth_enabled.Assign(regs.zeta_enable != 0 ? 1 : 0);
|
depth_enabled.Assign(regs.zeta_enable != 0 ? 1 : 0);
|
||||||
depth_format.Assign(static_cast<u32>(regs.zeta.format));
|
depth_format.Assign(static_cast<u32>(regs.zeta.format));
|
||||||
y_negate.Assign(regs.screen_y_control.y_negate != 0 ? 1 : 0);
|
y_negate.Assign(regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft ? 1 : 0);
|
||||||
provoking_vertex_last.Assign(regs.provoking_vertex_last != 0 ? 1 : 0);
|
provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0);
|
||||||
conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0);
|
smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0);
|
||||||
smooth_lines.Assign(regs.line_smooth_enable != 0 ? 1 : 0);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < regs.rt.size(); ++i) {
|
for (size_t i = 0; i < regs.rt.size(); ++i) {
|
||||||
color_formats[i] = static_cast<u8>(regs.rt[i].format);
|
color_formats[i] = static_cast<u8>(regs.rt[i].format);
|
||||||
|
@ -116,8 +118,8 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
|
||||||
maxwell3d.dirty.flags[Dirty::VertexInput] = false;
|
maxwell3d.dirty.flags[Dirty::VertexInput] = false;
|
||||||
enabled_divisors = 0;
|
enabled_divisors = 0;
|
||||||
for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
||||||
const bool is_enabled = regs.instanced_arrays.IsInstancingEnabled(index);
|
const bool is_enabled = regs.vertex_stream_instances.IsInstancingEnabled(index);
|
||||||
binding_divisors[index] = is_enabled ? regs.vertex_array[index].divisor : 0;
|
binding_divisors[index] = is_enabled ? regs.vertex_streams[index].frequency : 0;
|
||||||
enabled_divisors |= (is_enabled ? u64{1} : 0) << index;
|
enabled_divisors |= (is_enabled ? u64{1} : 0) << index;
|
||||||
}
|
}
|
||||||
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
|
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
|
||||||
|
@ -164,17 +166,17 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
|
||||||
|
|
||||||
// TODO: C++20 Use templated lambda to deduplicate code
|
// TODO: C++20 Use templated lambda to deduplicate code
|
||||||
|
|
||||||
if (!regs.independent_blend_enable) {
|
if (!regs.blend_per_target_enabled) {
|
||||||
const auto& src = regs.blend;
|
if (!regs.blend.enable[index]) {
|
||||||
if (!src.enable[index]) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
equation_rgb.Assign(PackBlendEquation(src.equation_rgb));
|
const auto& src = regs.blend;
|
||||||
equation_a.Assign(PackBlendEquation(src.equation_a));
|
equation_rgb.Assign(PackBlendEquation(src.color_op));
|
||||||
factor_source_rgb.Assign(PackBlendFactor(src.factor_source_rgb));
|
equation_a.Assign(PackBlendEquation(src.alpha_op));
|
||||||
factor_dest_rgb.Assign(PackBlendFactor(src.factor_dest_rgb));
|
factor_source_rgb.Assign(PackBlendFactor(src.color_source));
|
||||||
factor_source_a.Assign(PackBlendFactor(src.factor_source_a));
|
factor_dest_rgb.Assign(PackBlendFactor(src.color_dest));
|
||||||
factor_dest_a.Assign(PackBlendFactor(src.factor_dest_a));
|
factor_source_a.Assign(PackBlendFactor(src.alpha_source));
|
||||||
|
factor_dest_a.Assign(PackBlendFactor(src.alpha_dest));
|
||||||
enable.Assign(1);
|
enable.Assign(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -182,34 +184,34 @@ void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t
|
||||||
if (!regs.blend.enable[index]) {
|
if (!regs.blend.enable[index]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& src = regs.independent_blend[index];
|
const auto& src = regs.blend_per_target[index];
|
||||||
equation_rgb.Assign(PackBlendEquation(src.equation_rgb));
|
equation_rgb.Assign(PackBlendEquation(src.color_op));
|
||||||
equation_a.Assign(PackBlendEquation(src.equation_a));
|
equation_a.Assign(PackBlendEquation(src.alpha_op));
|
||||||
factor_source_rgb.Assign(PackBlendFactor(src.factor_source_rgb));
|
factor_source_rgb.Assign(PackBlendFactor(src.color_source));
|
||||||
factor_dest_rgb.Assign(PackBlendFactor(src.factor_dest_rgb));
|
factor_dest_rgb.Assign(PackBlendFactor(src.color_dest));
|
||||||
factor_source_a.Assign(PackBlendFactor(src.factor_source_a));
|
factor_source_a.Assign(PackBlendFactor(src.alpha_source));
|
||||||
factor_dest_a.Assign(PackBlendFactor(src.factor_dest_a));
|
factor_dest_a.Assign(PackBlendFactor(src.alpha_dest));
|
||||||
enable.Assign(1);
|
enable.Assign(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
|
void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
|
||||||
u32 packed_front_face = PackFrontFace(regs.front_face);
|
u32 packed_front_face = PackFrontFace(regs.gl_front_face);
|
||||||
if (regs.screen_y_control.triangle_rast_flip != 0) {
|
if (regs.window_origin.flip_y != 0) {
|
||||||
// Flip front face
|
// Flip front face
|
||||||
packed_front_face = 1 - packed_front_face;
|
packed_front_face = 1 - packed_front_face;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw1 = 0;
|
raw1 = 0;
|
||||||
raw2 = 0;
|
raw2 = 0;
|
||||||
front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
|
front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op.fail));
|
||||||
front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op_zfail));
|
front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op.zfail));
|
||||||
front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op_zpass));
|
front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op.zpass));
|
||||||
front.test_func.Assign(PackComparisonOp(regs.stencil_front_func_func));
|
front.test_func.Assign(PackComparisonOp(regs.stencil_front_op.func));
|
||||||
if (regs.stencil_two_side_enable) {
|
if (regs.stencil_two_side_enable) {
|
||||||
back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op_fail));
|
back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op.fail));
|
||||||
back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op_zfail));
|
back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op.zfail));
|
||||||
back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op_zpass));
|
back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op.zpass));
|
||||||
back.test_func.Assign(PackComparisonOp(regs.stencil_back_func_func));
|
back.test_func.Assign(PackComparisonOp(regs.stencil_back_op.func));
|
||||||
} else {
|
} else {
|
||||||
back.action_stencil_fail.Assign(front.action_stencil_fail);
|
back.action_stencil_fail.Assign(front.action_stencil_fail);
|
||||||
back.action_depth_fail.Assign(front.action_depth_fail);
|
back.action_depth_fail.Assign(front.action_depth_fail);
|
||||||
|
@ -222,9 +224,9 @@ void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
|
||||||
depth_test_enable.Assign(regs.depth_test_enable);
|
depth_test_enable.Assign(regs.depth_test_enable);
|
||||||
front_face.Assign(packed_front_face);
|
front_face.Assign(packed_front_face);
|
||||||
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
||||||
cull_face.Assign(PackCullFace(regs.cull_face));
|
cull_face.Assign(PackCullFace(regs.gl_cull_face));
|
||||||
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
|
cull_enable.Assign(regs.gl_cull_test_enabled != 0 ? 1 : 0);
|
||||||
std::ranges::transform(regs.vertex_array, vertex_strides.begin(), [](const auto& array) {
|
std::ranges::transform(regs.vertex_streams, vertex_strides.begin(), [](const auto& array) {
|
||||||
return static_cast<u16>(array.stride.Value());
|
return static_cast<u16>(array.stride.Value());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -251,41 +253,42 @@ Maxwell::ComparisonOp FixedPipelineState::UnpackComparisonOp(u32 packed) noexcep
|
||||||
return static_cast<Maxwell::ComparisonOp>(packed + 1);
|
return static_cast<Maxwell::ComparisonOp>(packed + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp op) noexcept {
|
u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp::Op op) noexcept {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Maxwell::StencilOp::Keep:
|
case Maxwell::StencilOp::Op::Keep_D3D:
|
||||||
case Maxwell::StencilOp::KeepOGL:
|
case Maxwell::StencilOp::Op::Keep_GL:
|
||||||
return 0;
|
return 0;
|
||||||
case Maxwell::StencilOp::Zero:
|
case Maxwell::StencilOp::Op::Zero_D3D:
|
||||||
case Maxwell::StencilOp::ZeroOGL:
|
case Maxwell::StencilOp::Op::Zero_GL:
|
||||||
return 1;
|
return 1;
|
||||||
case Maxwell::StencilOp::Replace:
|
case Maxwell::StencilOp::Op::Replace_D3D:
|
||||||
case Maxwell::StencilOp::ReplaceOGL:
|
case Maxwell::StencilOp::Op::Replace_GL:
|
||||||
return 2;
|
return 2;
|
||||||
case Maxwell::StencilOp::Incr:
|
case Maxwell::StencilOp::Op::IncrSaturate_D3D:
|
||||||
case Maxwell::StencilOp::IncrOGL:
|
case Maxwell::StencilOp::Op::IncrSaturate_GL:
|
||||||
return 3;
|
return 3;
|
||||||
case Maxwell::StencilOp::Decr:
|
case Maxwell::StencilOp::Op::DecrSaturate_D3D:
|
||||||
case Maxwell::StencilOp::DecrOGL:
|
case Maxwell::StencilOp::Op::DecrSaturate_GL:
|
||||||
return 4;
|
return 4;
|
||||||
case Maxwell::StencilOp::Invert:
|
case Maxwell::StencilOp::Op::Invert_D3D:
|
||||||
case Maxwell::StencilOp::InvertOGL:
|
case Maxwell::StencilOp::Op::Invert_GL:
|
||||||
return 5;
|
return 5;
|
||||||
case Maxwell::StencilOp::IncrWrap:
|
case Maxwell::StencilOp::Op::Incr_D3D:
|
||||||
case Maxwell::StencilOp::IncrWrapOGL:
|
case Maxwell::StencilOp::Op::Incr_GL:
|
||||||
return 6;
|
return 6;
|
||||||
case Maxwell::StencilOp::DecrWrap:
|
case Maxwell::StencilOp::Op::Decr_D3D:
|
||||||
case Maxwell::StencilOp::DecrWrapOGL:
|
case Maxwell::StencilOp::Op::Decr_GL:
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxwell::StencilOp FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
|
Maxwell::StencilOp::Op FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
|
||||||
static constexpr std::array LUT = {Maxwell::StencilOp::Keep, Maxwell::StencilOp::Zero,
|
static constexpr std::array LUT = {
|
||||||
Maxwell::StencilOp::Replace, Maxwell::StencilOp::Incr,
|
Maxwell::StencilOp::Op::Keep_D3D, Maxwell::StencilOp::Op::Zero_D3D,
|
||||||
Maxwell::StencilOp::Decr, Maxwell::StencilOp::Invert,
|
Maxwell::StencilOp::Op::Replace_D3D, Maxwell::StencilOp::Op::IncrSaturate_D3D,
|
||||||
Maxwell::StencilOp::IncrWrap, Maxwell::StencilOp::DecrWrap};
|
Maxwell::StencilOp::Op::DecrSaturate_D3D, Maxwell::StencilOp::Op::Invert_D3D,
|
||||||
|
Maxwell::StencilOp::Op::Incr_D3D, Maxwell::StencilOp::Op::Decr_D3D};
|
||||||
return LUT[packed];
|
return LUT[packed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,30 +321,30 @@ Maxwell::PolygonMode FixedPipelineState::UnpackPolygonMode(u32 packed) noexcept
|
||||||
return static_cast<Maxwell::PolygonMode>(packed + 0x1B00);
|
return static_cast<Maxwell::PolygonMode>(packed + 0x1B00);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOperation op) noexcept {
|
u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOp::Op op) noexcept {
|
||||||
return static_cast<u32>(op) - 0x1500;
|
return static_cast<u32>(op) - 0x1500;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxwell::LogicOperation FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
|
Maxwell::LogicOp::Op FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
|
||||||
return static_cast<Maxwell::LogicOperation>(packed + 0x1500);
|
return static_cast<Maxwell::LogicOp::Op>(packed + 0x1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noexcept {
|
u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noexcept {
|
||||||
switch (equation) {
|
switch (equation) {
|
||||||
case Maxwell::Blend::Equation::Add:
|
case Maxwell::Blend::Equation::Add_D3D:
|
||||||
case Maxwell::Blend::Equation::AddGL:
|
case Maxwell::Blend::Equation::Add_GL:
|
||||||
return 0;
|
return 0;
|
||||||
case Maxwell::Blend::Equation::Subtract:
|
case Maxwell::Blend::Equation::Subtract_D3D:
|
||||||
case Maxwell::Blend::Equation::SubtractGL:
|
case Maxwell::Blend::Equation::Subtract_GL:
|
||||||
return 1;
|
return 1;
|
||||||
case Maxwell::Blend::Equation::ReverseSubtract:
|
case Maxwell::Blend::Equation::ReverseSubtract_D3D:
|
||||||
case Maxwell::Blend::Equation::ReverseSubtractGL:
|
case Maxwell::Blend::Equation::ReverseSubtract_GL:
|
||||||
return 2;
|
return 2;
|
||||||
case Maxwell::Blend::Equation::Min:
|
case Maxwell::Blend::Equation::Min_D3D:
|
||||||
case Maxwell::Blend::Equation::MinGL:
|
case Maxwell::Blend::Equation::Min_GL:
|
||||||
return 3;
|
return 3;
|
||||||
case Maxwell::Blend::Equation::Max:
|
case Maxwell::Blend::Equation::Max_D3D:
|
||||||
case Maxwell::Blend::Equation::MaxGL:
|
case Maxwell::Blend::Equation::Max_GL:
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -349,97 +352,99 @@ u32 FixedPipelineState::PackBlendEquation(Maxwell::Blend::Equation equation) noe
|
||||||
|
|
||||||
Maxwell::Blend::Equation FixedPipelineState::UnpackBlendEquation(u32 packed) noexcept {
|
Maxwell::Blend::Equation FixedPipelineState::UnpackBlendEquation(u32 packed) noexcept {
|
||||||
static constexpr std::array LUT = {
|
static constexpr std::array LUT = {
|
||||||
Maxwell::Blend::Equation::Add, Maxwell::Blend::Equation::Subtract,
|
Maxwell::Blend::Equation::Add_D3D, Maxwell::Blend::Equation::Subtract_D3D,
|
||||||
Maxwell::Blend::Equation::ReverseSubtract, Maxwell::Blend::Equation::Min,
|
Maxwell::Blend::Equation::ReverseSubtract_D3D, Maxwell::Blend::Equation::Min_D3D,
|
||||||
Maxwell::Blend::Equation::Max};
|
Maxwell::Blend::Equation::Max_D3D};
|
||||||
return LUT[packed];
|
return LUT[packed];
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 FixedPipelineState::PackBlendFactor(Maxwell::Blend::Factor factor) noexcept {
|
u32 FixedPipelineState::PackBlendFactor(Maxwell::Blend::Factor factor) noexcept {
|
||||||
switch (factor) {
|
switch (factor) {
|
||||||
case Maxwell::Blend::Factor::Zero:
|
case Maxwell::Blend::Factor::Zero_D3D:
|
||||||
case Maxwell::Blend::Factor::ZeroGL:
|
case Maxwell::Blend::Factor::Zero_GL:
|
||||||
return 0;
|
return 0;
|
||||||
case Maxwell::Blend::Factor::One:
|
case Maxwell::Blend::Factor::One_D3D:
|
||||||
case Maxwell::Blend::Factor::OneGL:
|
case Maxwell::Blend::Factor::One_GL:
|
||||||
return 1;
|
return 1;
|
||||||
case Maxwell::Blend::Factor::SourceColor:
|
case Maxwell::Blend::Factor::SourceColor_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceColorGL:
|
case Maxwell::Blend::Factor::SourceColor_GL:
|
||||||
return 2;
|
return 2;
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceColor:
|
case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceColorGL:
|
case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
|
||||||
return 3;
|
return 3;
|
||||||
case Maxwell::Blend::Factor::SourceAlpha:
|
case Maxwell::Blend::Factor::SourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceAlphaGL:
|
case Maxwell::Blend::Factor::SourceAlpha_GL:
|
||||||
return 4;
|
return 4;
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
|
case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
|
||||||
return 5;
|
return 5;
|
||||||
case Maxwell::Blend::Factor::DestAlpha:
|
case Maxwell::Blend::Factor::DestAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::DestAlphaGL:
|
case Maxwell::Blend::Factor::DestAlpha_GL:
|
||||||
return 6;
|
return 6;
|
||||||
case Maxwell::Blend::Factor::OneMinusDestAlpha:
|
case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
|
||||||
return 7;
|
return 7;
|
||||||
case Maxwell::Blend::Factor::DestColor:
|
case Maxwell::Blend::Factor::DestColor_D3D:
|
||||||
case Maxwell::Blend::Factor::DestColorGL:
|
case Maxwell::Blend::Factor::DestColor_GL:
|
||||||
return 8;
|
return 8;
|
||||||
case Maxwell::Blend::Factor::OneMinusDestColor:
|
case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusDestColorGL:
|
case Maxwell::Blend::Factor::OneMinusDestColor_GL:
|
||||||
return 9;
|
return 9;
|
||||||
case Maxwell::Blend::Factor::SourceAlphaSaturate:
|
case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
|
case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
|
||||||
return 10;
|
return 10;
|
||||||
case Maxwell::Blend::Factor::Source1Color:
|
case Maxwell::Blend::Factor::Source1Color_D3D:
|
||||||
case Maxwell::Blend::Factor::Source1ColorGL:
|
case Maxwell::Blend::Factor::Source1Color_GL:
|
||||||
return 11;
|
return 11;
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1Color:
|
case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
|
case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
|
||||||
return 12;
|
return 12;
|
||||||
case Maxwell::Blend::Factor::Source1Alpha:
|
case Maxwell::Blend::Factor::Source1Alpha_D3D:
|
||||||
case Maxwell::Blend::Factor::Source1AlphaGL:
|
case Maxwell::Blend::Factor::Source1Alpha_GL:
|
||||||
return 13;
|
return 13;
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
|
case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
|
case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
|
||||||
return 14;
|
return 14;
|
||||||
case Maxwell::Blend::Factor::ConstantColor:
|
case Maxwell::Blend::Factor::BlendFactor_D3D:
|
||||||
case Maxwell::Blend::Factor::ConstantColorGL:
|
case Maxwell::Blend::Factor::ConstantColor_GL:
|
||||||
return 15;
|
return 15;
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantColor:
|
case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantColorGL:
|
case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
|
||||||
return 16;
|
return 16;
|
||||||
case Maxwell::Blend::Factor::ConstantAlpha:
|
case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::ConstantAlphaGL:
|
case Maxwell::Blend::Factor::ConstantAlpha_GL:
|
||||||
return 17;
|
return 17;
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
|
case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
|
||||||
return 18;
|
return 18;
|
||||||
}
|
}
|
||||||
|
UNIMPLEMENTED_MSG("Unknown blend factor {}", static_cast<u32>(factor));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxwell::Blend::Factor FixedPipelineState::UnpackBlendFactor(u32 packed) noexcept {
|
Maxwell::Blend::Factor FixedPipelineState::UnpackBlendFactor(u32 packed) noexcept {
|
||||||
static constexpr std::array LUT = {
|
static constexpr std::array LUT = {
|
||||||
Maxwell::Blend::Factor::Zero,
|
Maxwell::Blend::Factor::Zero_D3D,
|
||||||
Maxwell::Blend::Factor::One,
|
Maxwell::Blend::Factor::One_D3D,
|
||||||
Maxwell::Blend::Factor::SourceColor,
|
Maxwell::Blend::Factor::SourceColor_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusSourceColor,
|
Maxwell::Blend::Factor::OneMinusSourceColor_D3D,
|
||||||
Maxwell::Blend::Factor::SourceAlpha,
|
Maxwell::Blend::Factor::SourceAlpha_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusSourceAlpha,
|
Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D,
|
||||||
Maxwell::Blend::Factor::DestAlpha,
|
Maxwell::Blend::Factor::DestAlpha_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusDestAlpha,
|
Maxwell::Blend::Factor::OneMinusDestAlpha_D3D,
|
||||||
Maxwell::Blend::Factor::DestColor,
|
Maxwell::Blend::Factor::DestColor_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusDestColor,
|
Maxwell::Blend::Factor::OneMinusDestColor_D3D,
|
||||||
Maxwell::Blend::Factor::SourceAlphaSaturate,
|
Maxwell::Blend::Factor::SourceAlphaSaturate_D3D,
|
||||||
Maxwell::Blend::Factor::Source1Color,
|
Maxwell::Blend::Factor::Source1Color_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusSource1Color,
|
Maxwell::Blend::Factor::OneMinusSource1Color_D3D,
|
||||||
Maxwell::Blend::Factor::Source1Alpha,
|
Maxwell::Blend::Factor::Source1Alpha_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusSource1Alpha,
|
Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D,
|
||||||
Maxwell::Blend::Factor::ConstantColor,
|
Maxwell::Blend::Factor::BlendFactor_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusConstantColor,
|
Maxwell::Blend::Factor::OneMinusBlendFactor_D3D,
|
||||||
Maxwell::Blend::Factor::ConstantAlpha,
|
Maxwell::Blend::Factor::BothSourceAlpha_D3D,
|
||||||
Maxwell::Blend::Factor::OneMinusConstantAlpha,
|
Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D,
|
||||||
};
|
};
|
||||||
|
ASSERT(packed < LUT.size());
|
||||||
return LUT[packed];
|
return LUT[packed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ struct FixedPipelineState {
|
||||||
static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
|
static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
|
||||||
static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
|
static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
|
||||||
|
|
||||||
static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
|
static u32 PackStencilOp(Maxwell::StencilOp::Op op) noexcept;
|
||||||
static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
|
static Maxwell::StencilOp::Op UnpackStencilOp(u32 packed) noexcept;
|
||||||
|
|
||||||
static u32 PackCullFace(Maxwell::CullFace cull) noexcept;
|
static u32 PackCullFace(Maxwell::CullFace cull) noexcept;
|
||||||
static Maxwell::CullFace UnpackCullFace(u32 packed) noexcept;
|
static Maxwell::CullFace UnpackCullFace(u32 packed) noexcept;
|
||||||
|
@ -33,8 +33,8 @@ struct FixedPipelineState {
|
||||||
static u32 PackPolygonMode(Maxwell::PolygonMode mode) noexcept;
|
static u32 PackPolygonMode(Maxwell::PolygonMode mode) noexcept;
|
||||||
static Maxwell::PolygonMode UnpackPolygonMode(u32 packed) noexcept;
|
static Maxwell::PolygonMode UnpackPolygonMode(u32 packed) noexcept;
|
||||||
|
|
||||||
static u32 PackLogicOp(Maxwell::LogicOperation op) noexcept;
|
static u32 PackLogicOp(Maxwell::LogicOp::Op op) noexcept;
|
||||||
static Maxwell::LogicOperation UnpackLogicOp(u32 packed) noexcept;
|
static Maxwell::LogicOp::Op UnpackLogicOp(u32 packed) noexcept;
|
||||||
|
|
||||||
static u32 PackBlendEquation(Maxwell::Blend::Equation equation) noexcept;
|
static u32 PackBlendEquation(Maxwell::Blend::Equation equation) noexcept;
|
||||||
static Maxwell::Blend::Equation UnpackBlendEquation(u32 packed) noexcept;
|
static Maxwell::Blend::Equation UnpackBlendEquation(u32 packed) noexcept;
|
||||||
|
@ -113,15 +113,15 @@ struct FixedPipelineState {
|
||||||
BitField<Position + 6, 3, u32> action_depth_pass;
|
BitField<Position + 6, 3, u32> action_depth_pass;
|
||||||
BitField<Position + 9, 3, u32> test_func;
|
BitField<Position + 9, 3, u32> test_func;
|
||||||
|
|
||||||
Maxwell::StencilOp ActionStencilFail() const noexcept {
|
Maxwell::StencilOp::Op ActionStencilFail() const noexcept {
|
||||||
return UnpackStencilOp(action_stencil_fail);
|
return UnpackStencilOp(action_stencil_fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxwell::StencilOp ActionDepthFail() const noexcept {
|
Maxwell::StencilOp::Op ActionDepthFail() const noexcept {
|
||||||
return UnpackStencilOp(action_depth_fail);
|
return UnpackStencilOp(action_depth_fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
Maxwell::StencilOp ActionDepthPass() const noexcept {
|
Maxwell::StencilOp::Op ActionDepthPass() const noexcept {
|
||||||
return UnpackStencilOp(action_depth_pass);
|
return UnpackStencilOp(action_depth_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,6 @@ struct FixedPipelineState {
|
||||||
BitField<6, 5, u32> depth_format;
|
BitField<6, 5, u32> depth_format;
|
||||||
BitField<11, 1, u32> y_negate;
|
BitField<11, 1, u32> y_negate;
|
||||||
BitField<12, 1, u32> provoking_vertex_last;
|
BitField<12, 1, u32> provoking_vertex_last;
|
||||||
BitField<13, 1, u32> conservative_raster_enable;
|
|
||||||
BitField<14, 1, u32> smooth_lines;
|
BitField<14, 1, u32> smooth_lines;
|
||||||
};
|
};
|
||||||
std::array<u8, Maxwell::NumRenderTargets> color_formats;
|
std::array<u8, Maxwell::NumRenderTargets> color_formats;
|
||||||
|
|
|
@ -323,161 +323,182 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
|
||||||
Maxwell::VertexAttribute::Size size) {
|
Maxwell::VertexAttribute::Size size) {
|
||||||
const VkFormat format{([&]() {
|
const VkFormat format{([&]() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedNorm:
|
case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
|
||||||
|
ASSERT_MSG(false, "Invalid vertex attribute type!");
|
||||||
|
break;
|
||||||
|
case Maxwell::VertexAttribute::Type::UNorm:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
return VK_FORMAT_R8_UNORM;
|
return VK_FORMAT_R8_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
return VK_FORMAT_R8G8_UNORM;
|
return VK_FORMAT_R8G8_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
return VK_FORMAT_R8G8B8_UNORM;
|
return VK_FORMAT_R8G8B8_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_UNORM;
|
return VK_FORMAT_R16_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_UNORM;
|
return VK_FORMAT_R16G16_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_UNORM;
|
return VK_FORMAT_R16G16B16_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_UNORM;
|
return VK_FORMAT_R16G16B16A16_UNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::SignedNorm:
|
case Maxwell::VertexAttribute::Type::SNorm:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
return VK_FORMAT_R8_SNORM;
|
return VK_FORMAT_R8_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
return VK_FORMAT_R8G8_SNORM;
|
return VK_FORMAT_R8G8_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
return VK_FORMAT_R8G8B8_SNORM;
|
return VK_FORMAT_R8G8B8_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return VK_FORMAT_R8G8B8A8_SNORM;
|
return VK_FORMAT_R8G8B8A8_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_SNORM;
|
return VK_FORMAT_R16_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_SNORM;
|
return VK_FORMAT_R16G16_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_SNORM;
|
return VK_FORMAT_R16G16B16_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_SNORM;
|
return VK_FORMAT_R16G16B16A16_SNORM;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return VK_FORMAT_A2B10G10R10_SNORM_PACK32;
|
return VK_FORMAT_A2B10G10R10_SNORM_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedScaled:
|
case Maxwell::VertexAttribute::Type::UScaled:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
return VK_FORMAT_R8_USCALED;
|
return VK_FORMAT_R8_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
return VK_FORMAT_R8G8_USCALED;
|
return VK_FORMAT_R8G8_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
return VK_FORMAT_R8G8B8_USCALED;
|
return VK_FORMAT_R8G8B8_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return VK_FORMAT_R8G8B8A8_USCALED;
|
return VK_FORMAT_R8G8B8A8_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_USCALED;
|
return VK_FORMAT_R16_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_USCALED;
|
return VK_FORMAT_R16G16_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_USCALED;
|
return VK_FORMAT_R16G16B16_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_USCALED;
|
return VK_FORMAT_R16G16B16A16_USCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return VK_FORMAT_A2B10G10R10_USCALED_PACK32;
|
return VK_FORMAT_A2B10G10R10_USCALED_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::SignedScaled:
|
case Maxwell::VertexAttribute::Type::SScaled:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
return VK_FORMAT_R8_SSCALED;
|
return VK_FORMAT_R8_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
return VK_FORMAT_R8G8_SSCALED;
|
return VK_FORMAT_R8G8_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
return VK_FORMAT_R8G8B8_SSCALED;
|
return VK_FORMAT_R8G8B8_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return VK_FORMAT_R8G8B8A8_SSCALED;
|
return VK_FORMAT_R8G8B8A8_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_SSCALED;
|
return VK_FORMAT_R16_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_SSCALED;
|
return VK_FORMAT_R16G16_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_SSCALED;
|
return VK_FORMAT_R16G16B16_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_SSCALED;
|
return VK_FORMAT_R16G16B16A16_SSCALED;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
|
return VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedInt:
|
case Maxwell::VertexAttribute::Type::UInt:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
return VK_FORMAT_R8_UINT;
|
return VK_FORMAT_R8_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
return VK_FORMAT_R8G8_UINT;
|
return VK_FORMAT_R8G8_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
return VK_FORMAT_R8G8B8_UINT;
|
return VK_FORMAT_R8G8B8_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return VK_FORMAT_R8G8B8A8_UINT;
|
return VK_FORMAT_R8G8B8A8_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_UINT;
|
return VK_FORMAT_R16_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_UINT;
|
return VK_FORMAT_R16G16_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_UINT;
|
return VK_FORMAT_R16G16B16_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_UINT;
|
return VK_FORMAT_R16G16B16A16_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32:
|
case Maxwell::VertexAttribute::Size::Size_R32:
|
||||||
return VK_FORMAT_R32_UINT;
|
return VK_FORMAT_R32_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32:
|
||||||
return VK_FORMAT_R32G32_UINT;
|
return VK_FORMAT_R32G32_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
|
||||||
return VK_FORMAT_R32G32B32_UINT;
|
return VK_FORMAT_R32G32B32_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
|
||||||
return VK_FORMAT_R32G32B32A32_UINT;
|
return VK_FORMAT_R32G32B32A32_UINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return VK_FORMAT_A2B10G10R10_UINT_PACK32;
|
return VK_FORMAT_A2B10G10R10_UINT_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::SignedInt:
|
case Maxwell::VertexAttribute::Type::SInt:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_8:
|
case Maxwell::VertexAttribute::Size::Size_R8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_A8:
|
||||||
return VK_FORMAT_R8_SINT;
|
return VK_FORMAT_R8_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_G8_R8:
|
||||||
return VK_FORMAT_R8G8_SINT;
|
return VK_FORMAT_R8G8_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
|
||||||
return VK_FORMAT_R8G8B8_SINT;
|
return VK_FORMAT_R8G8B8_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
|
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
|
||||||
|
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
|
||||||
return VK_FORMAT_R8G8B8A8_SINT;
|
return VK_FORMAT_R8G8B8A8_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_SINT;
|
return VK_FORMAT_R16_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_SINT;
|
return VK_FORMAT_R16G16_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_SINT;
|
return VK_FORMAT_R16G16B16_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_SINT;
|
return VK_FORMAT_R16G16B16A16_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32:
|
case Maxwell::VertexAttribute::Size::Size_R32:
|
||||||
return VK_FORMAT_R32_SINT;
|
return VK_FORMAT_R32_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32:
|
||||||
return VK_FORMAT_R32G32_SINT;
|
return VK_FORMAT_R32G32_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
|
||||||
return VK_FORMAT_R32G32B32_SINT;
|
return VK_FORMAT_R32G32B32_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
|
||||||
return VK_FORMAT_R32G32B32A32_SINT;
|
return VK_FORMAT_R32G32B32A32_SINT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_10_10_10_2:
|
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
|
||||||
return VK_FORMAT_A2B10G10R10_SINT_PACK32;
|
return VK_FORMAT_A2B10G10R10_SINT_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -485,23 +506,23 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
|
||||||
break;
|
break;
|
||||||
case Maxwell::VertexAttribute::Type::Float:
|
case Maxwell::VertexAttribute::Type::Float:
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case Maxwell::VertexAttribute::Size::Size_16:
|
case Maxwell::VertexAttribute::Size::Size_R16:
|
||||||
return VK_FORMAT_R16_SFLOAT;
|
return VK_FORMAT_R16_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16:
|
||||||
return VK_FORMAT_R16G16_SFLOAT;
|
return VK_FORMAT_R16G16_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
|
||||||
return VK_FORMAT_R16G16B16_SFLOAT;
|
return VK_FORMAT_R16G16B16_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
|
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
|
||||||
return VK_FORMAT_R16G16B16A16_SFLOAT;
|
return VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32:
|
case Maxwell::VertexAttribute::Size::Size_R32:
|
||||||
return VK_FORMAT_R32_SFLOAT;
|
return VK_FORMAT_R32_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32:
|
||||||
return VK_FORMAT_R32G32_SFLOAT;
|
return VK_FORMAT_R32G32_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
|
||||||
return VK_FORMAT_R32G32B32_SFLOAT;
|
return VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_32_32_32_32:
|
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
|
||||||
return VK_FORMAT_R32G32B32A32_SFLOAT;
|
return VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
case Maxwell::VertexAttribute::Size::Size_11_11_10:
|
case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
|
||||||
return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
|
return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -521,29 +542,29 @@ VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
|
||||||
|
|
||||||
VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison) {
|
VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison) {
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Maxwell::ComparisonOp::Never:
|
case Maxwell::ComparisonOp::Never_D3D:
|
||||||
case Maxwell::ComparisonOp::NeverOld:
|
case Maxwell::ComparisonOp::Never_GL:
|
||||||
return VK_COMPARE_OP_NEVER;
|
return VK_COMPARE_OP_NEVER;
|
||||||
case Maxwell::ComparisonOp::Less:
|
case Maxwell::ComparisonOp::Less_D3D:
|
||||||
case Maxwell::ComparisonOp::LessOld:
|
case Maxwell::ComparisonOp::Less_GL:
|
||||||
return VK_COMPARE_OP_LESS;
|
return VK_COMPARE_OP_LESS;
|
||||||
case Maxwell::ComparisonOp::Equal:
|
case Maxwell::ComparisonOp::Equal_D3D:
|
||||||
case Maxwell::ComparisonOp::EqualOld:
|
case Maxwell::ComparisonOp::Equal_GL:
|
||||||
return VK_COMPARE_OP_EQUAL;
|
return VK_COMPARE_OP_EQUAL;
|
||||||
case Maxwell::ComparisonOp::LessEqual:
|
case Maxwell::ComparisonOp::LessEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::LessEqualOld:
|
case Maxwell::ComparisonOp::LessEqual_GL:
|
||||||
return VK_COMPARE_OP_LESS_OR_EQUAL;
|
return VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||||
case Maxwell::ComparisonOp::Greater:
|
case Maxwell::ComparisonOp::Greater_D3D:
|
||||||
case Maxwell::ComparisonOp::GreaterOld:
|
case Maxwell::ComparisonOp::Greater_GL:
|
||||||
return VK_COMPARE_OP_GREATER;
|
return VK_COMPARE_OP_GREATER;
|
||||||
case Maxwell::ComparisonOp::NotEqual:
|
case Maxwell::ComparisonOp::NotEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::NotEqualOld:
|
case Maxwell::ComparisonOp::NotEqual_GL:
|
||||||
return VK_COMPARE_OP_NOT_EQUAL;
|
return VK_COMPARE_OP_NOT_EQUAL;
|
||||||
case Maxwell::ComparisonOp::GreaterEqual:
|
case Maxwell::ComparisonOp::GreaterEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::GreaterEqualOld:
|
case Maxwell::ComparisonOp::GreaterEqual_GL:
|
||||||
return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
||||||
case Maxwell::ComparisonOp::Always:
|
case Maxwell::ComparisonOp::Always_D3D:
|
||||||
case Maxwell::ComparisonOp::AlwaysOld:
|
case Maxwell::ComparisonOp::Always_GL:
|
||||||
return VK_COMPARE_OP_ALWAYS;
|
return VK_COMPARE_OP_ALWAYS;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
|
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
|
||||||
|
@ -563,31 +584,31 @@ VkIndexType IndexFormat(Maxwell::IndexFormat index_format) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
VkStencilOp StencilOp(Maxwell::StencilOp stencil_op) {
|
VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op) {
|
||||||
switch (stencil_op) {
|
switch (stencil_op) {
|
||||||
case Maxwell::StencilOp::Keep:
|
case Maxwell::StencilOp::Op::Keep_D3D:
|
||||||
case Maxwell::StencilOp::KeepOGL:
|
case Maxwell::StencilOp::Op::Keep_GL:
|
||||||
return VK_STENCIL_OP_KEEP;
|
return VK_STENCIL_OP_KEEP;
|
||||||
case Maxwell::StencilOp::Zero:
|
case Maxwell::StencilOp::Op::Zero_D3D:
|
||||||
case Maxwell::StencilOp::ZeroOGL:
|
case Maxwell::StencilOp::Op::Zero_GL:
|
||||||
return VK_STENCIL_OP_ZERO;
|
return VK_STENCIL_OP_ZERO;
|
||||||
case Maxwell::StencilOp::Replace:
|
case Maxwell::StencilOp::Op::Replace_D3D:
|
||||||
case Maxwell::StencilOp::ReplaceOGL:
|
case Maxwell::StencilOp::Op::Replace_GL:
|
||||||
return VK_STENCIL_OP_REPLACE;
|
return VK_STENCIL_OP_REPLACE;
|
||||||
case Maxwell::StencilOp::Incr:
|
case Maxwell::StencilOp::Op::IncrSaturate_D3D:
|
||||||
case Maxwell::StencilOp::IncrOGL:
|
case Maxwell::StencilOp::Op::IncrSaturate_GL:
|
||||||
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
|
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
|
||||||
case Maxwell::StencilOp::Decr:
|
case Maxwell::StencilOp::Op::DecrSaturate_D3D:
|
||||||
case Maxwell::StencilOp::DecrOGL:
|
case Maxwell::StencilOp::Op::DecrSaturate_GL:
|
||||||
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
|
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
|
||||||
case Maxwell::StencilOp::Invert:
|
case Maxwell::StencilOp::Op::Invert_D3D:
|
||||||
case Maxwell::StencilOp::InvertOGL:
|
case Maxwell::StencilOp::Op::Invert_GL:
|
||||||
return VK_STENCIL_OP_INVERT;
|
return VK_STENCIL_OP_INVERT;
|
||||||
case Maxwell::StencilOp::IncrWrap:
|
case Maxwell::StencilOp::Op::Incr_D3D:
|
||||||
case Maxwell::StencilOp::IncrWrapOGL:
|
case Maxwell::StencilOp::Op::Incr_GL:
|
||||||
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
|
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
|
||||||
case Maxwell::StencilOp::DecrWrap:
|
case Maxwell::StencilOp::Op::Decr_D3D:
|
||||||
case Maxwell::StencilOp::DecrWrapOGL:
|
case Maxwell::StencilOp::Op::Decr_GL:
|
||||||
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
|
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil_op);
|
UNIMPLEMENTED_MSG("Unimplemented stencil op={}", stencil_op);
|
||||||
|
@ -596,20 +617,20 @@ VkStencilOp StencilOp(Maxwell::StencilOp stencil_op) {
|
||||||
|
|
||||||
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
|
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
|
||||||
switch (equation) {
|
switch (equation) {
|
||||||
case Maxwell::Blend::Equation::Add:
|
case Maxwell::Blend::Equation::Add_D3D:
|
||||||
case Maxwell::Blend::Equation::AddGL:
|
case Maxwell::Blend::Equation::Add_GL:
|
||||||
return VK_BLEND_OP_ADD;
|
return VK_BLEND_OP_ADD;
|
||||||
case Maxwell::Blend::Equation::Subtract:
|
case Maxwell::Blend::Equation::Subtract_D3D:
|
||||||
case Maxwell::Blend::Equation::SubtractGL:
|
case Maxwell::Blend::Equation::Subtract_GL:
|
||||||
return VK_BLEND_OP_SUBTRACT;
|
return VK_BLEND_OP_SUBTRACT;
|
||||||
case Maxwell::Blend::Equation::ReverseSubtract:
|
case Maxwell::Blend::Equation::ReverseSubtract_D3D:
|
||||||
case Maxwell::Blend::Equation::ReverseSubtractGL:
|
case Maxwell::Blend::Equation::ReverseSubtract_GL:
|
||||||
return VK_BLEND_OP_REVERSE_SUBTRACT;
|
return VK_BLEND_OP_REVERSE_SUBTRACT;
|
||||||
case Maxwell::Blend::Equation::Min:
|
case Maxwell::Blend::Equation::Min_D3D:
|
||||||
case Maxwell::Blend::Equation::MinGL:
|
case Maxwell::Blend::Equation::Min_GL:
|
||||||
return VK_BLEND_OP_MIN;
|
return VK_BLEND_OP_MIN;
|
||||||
case Maxwell::Blend::Equation::Max:
|
case Maxwell::Blend::Equation::Max_D3D:
|
||||||
case Maxwell::Blend::Equation::MaxGL:
|
case Maxwell::Blend::Equation::Max_GL:
|
||||||
return VK_BLEND_OP_MAX;
|
return VK_BLEND_OP_MAX;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
|
UNIMPLEMENTED_MSG("Unimplemented blend equation={}", equation);
|
||||||
|
@ -618,62 +639,62 @@ VkBlendOp BlendEquation(Maxwell::Blend::Equation equation) {
|
||||||
|
|
||||||
VkBlendFactor BlendFactor(Maxwell::Blend::Factor factor) {
|
VkBlendFactor BlendFactor(Maxwell::Blend::Factor factor) {
|
||||||
switch (factor) {
|
switch (factor) {
|
||||||
case Maxwell::Blend::Factor::Zero:
|
case Maxwell::Blend::Factor::Zero_D3D:
|
||||||
case Maxwell::Blend::Factor::ZeroGL:
|
case Maxwell::Blend::Factor::Zero_GL:
|
||||||
return VK_BLEND_FACTOR_ZERO;
|
return VK_BLEND_FACTOR_ZERO;
|
||||||
case Maxwell::Blend::Factor::One:
|
case Maxwell::Blend::Factor::One_D3D:
|
||||||
case Maxwell::Blend::Factor::OneGL:
|
case Maxwell::Blend::Factor::One_GL:
|
||||||
return VK_BLEND_FACTOR_ONE;
|
return VK_BLEND_FACTOR_ONE;
|
||||||
case Maxwell::Blend::Factor::SourceColor:
|
case Maxwell::Blend::Factor::SourceColor_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceColorGL:
|
case Maxwell::Blend::Factor::SourceColor_GL:
|
||||||
return VK_BLEND_FACTOR_SRC_COLOR;
|
return VK_BLEND_FACTOR_SRC_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceColor:
|
case Maxwell::Blend::Factor::OneMinusSourceColor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceColorGL:
|
case Maxwell::Blend::Factor::OneMinusSourceColor_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
|
||||||
case Maxwell::Blend::Factor::SourceAlpha:
|
case Maxwell::Blend::Factor::SourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceAlphaGL:
|
case Maxwell::Blend::Factor::SourceAlpha_GL:
|
||||||
return VK_BLEND_FACTOR_SRC_ALPHA;
|
return VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
|
case Maxwell::Blend::Factor::OneMinusSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSourceAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusSourceAlpha_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
case Maxwell::Blend::Factor::DestAlpha:
|
case Maxwell::Blend::Factor::DestAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::DestAlphaGL:
|
case Maxwell::Blend::Factor::DestAlpha_GL:
|
||||||
return VK_BLEND_FACTOR_DST_ALPHA;
|
return VK_BLEND_FACTOR_DST_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusDestAlpha:
|
case Maxwell::Blend::Factor::OneMinusDestAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusDestAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusDestAlpha_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
|
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
|
||||||
case Maxwell::Blend::Factor::DestColor:
|
case Maxwell::Blend::Factor::DestColor_D3D:
|
||||||
case Maxwell::Blend::Factor::DestColorGL:
|
case Maxwell::Blend::Factor::DestColor_GL:
|
||||||
return VK_BLEND_FACTOR_DST_COLOR;
|
return VK_BLEND_FACTOR_DST_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusDestColor:
|
case Maxwell::Blend::Factor::OneMinusDestColor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusDestColorGL:
|
case Maxwell::Blend::Factor::OneMinusDestColor_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
|
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
|
||||||
case Maxwell::Blend::Factor::SourceAlphaSaturate:
|
case Maxwell::Blend::Factor::SourceAlphaSaturate_D3D:
|
||||||
case Maxwell::Blend::Factor::SourceAlphaSaturateGL:
|
case Maxwell::Blend::Factor::SourceAlphaSaturate_GL:
|
||||||
return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
|
return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
|
||||||
case Maxwell::Blend::Factor::Source1Color:
|
case Maxwell::Blend::Factor::Source1Color_D3D:
|
||||||
case Maxwell::Blend::Factor::Source1ColorGL:
|
case Maxwell::Blend::Factor::Source1Color_GL:
|
||||||
return VK_BLEND_FACTOR_SRC1_COLOR;
|
return VK_BLEND_FACTOR_SRC1_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1Color:
|
case Maxwell::Blend::Factor::OneMinusSource1Color_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1ColorGL:
|
case Maxwell::Blend::Factor::OneMinusSource1Color_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
|
||||||
case Maxwell::Blend::Factor::Source1Alpha:
|
case Maxwell::Blend::Factor::Source1Alpha_D3D:
|
||||||
case Maxwell::Blend::Factor::Source1AlphaGL:
|
case Maxwell::Blend::Factor::Source1Alpha_GL:
|
||||||
return VK_BLEND_FACTOR_SRC1_ALPHA;
|
return VK_BLEND_FACTOR_SRC1_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
|
case Maxwell::Blend::Factor::OneMinusSource1Alpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusSource1AlphaGL:
|
case Maxwell::Blend::Factor::OneMinusSource1Alpha_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
|
||||||
case Maxwell::Blend::Factor::ConstantColor:
|
case Maxwell::Blend::Factor::BlendFactor_D3D:
|
||||||
case Maxwell::Blend::Factor::ConstantColorGL:
|
case Maxwell::Blend::Factor::ConstantColor_GL:
|
||||||
return VK_BLEND_FACTOR_CONSTANT_COLOR;
|
return VK_BLEND_FACTOR_CONSTANT_COLOR;
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantColor:
|
case Maxwell::Blend::Factor::OneMinusBlendFactor_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantColorGL:
|
case Maxwell::Blend::Factor::OneMinusConstantColor_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
|
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
|
||||||
case Maxwell::Blend::Factor::ConstantAlpha:
|
case Maxwell::Blend::Factor::BothSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::ConstantAlphaGL:
|
case Maxwell::Blend::Factor::ConstantAlpha_GL:
|
||||||
return VK_BLEND_FACTOR_CONSTANT_ALPHA;
|
return VK_BLEND_FACTOR_CONSTANT_ALPHA;
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
|
case Maxwell::Blend::Factor::OneMinusBothSourceAlpha_D3D:
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusConstantAlpha_GL:
|
||||||
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
|
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
|
UNIMPLEMENTED_MSG("Unimplemented blend factor={}", factor);
|
||||||
|
|
|
@ -55,7 +55,7 @@ VkCompareOp ComparisonOp(Maxwell::ComparisonOp comparison);
|
||||||
|
|
||||||
VkIndexType IndexFormat(Maxwell::IndexFormat index_format);
|
VkIndexType IndexFormat(Maxwell::IndexFormat index_format);
|
||||||
|
|
||||||
VkStencilOp StencilOp(Maxwell::StencilOp stencil_op);
|
VkStencilOp StencilOp(Maxwell::StencilOp::Op stencil_op);
|
||||||
|
|
||||||
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation);
|
VkBlendOp BlendEquation(Maxwell::Blend::Equation equation);
|
||||||
|
|
||||||
|
|
|
@ -288,7 +288,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||||
buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes);
|
buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes);
|
||||||
|
|
||||||
const auto& regs{maxwell3d->regs};
|
const auto& regs{maxwell3d->regs};
|
||||||
const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
|
const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
|
||||||
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
|
const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
|
||||||
const Shader::Info& info{stage_infos[stage]};
|
const Shader::Info& info{stage_infos[stage]};
|
||||||
buffer_cache.UnbindGraphicsStorageBuffers(stage);
|
buffer_cache.UnbindGraphicsStorageBuffers(stage);
|
||||||
|
@ -664,15 +664,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.lineStippleFactor = 0,
|
.lineStippleFactor = 0,
|
||||||
.lineStipplePattern = 0,
|
.lineStipplePattern = 0,
|
||||||
};
|
};
|
||||||
VkPipelineRasterizationConservativeStateCreateInfoEXT conservative_raster{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.conservativeRasterizationMode = key.state.conservative_raster_enable != 0
|
|
||||||
? VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
|
|
||||||
: VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
|
|
||||||
.extraPrimitiveOverestimationSize = 0.0f,
|
|
||||||
};
|
|
||||||
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{
|
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -683,9 +674,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
|
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
|
||||||
line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state);
|
line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state);
|
||||||
}
|
}
|
||||||
if (device.IsExtConservativeRasterizationSupported()) {
|
|
||||||
conservative_raster.pNext = std::exchange(rasterization_ci.pNext, &conservative_raster);
|
|
||||||
}
|
|
||||||
if (device.IsExtProvokingVertexSupported()) {
|
if (device.IsExtProvokingVertexSupported()) {
|
||||||
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
|
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,29 +62,29 @@ auto MakeSpan(Container& container) {
|
||||||
|
|
||||||
Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) {
|
Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) {
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Maxwell::ComparisonOp::Never:
|
case Maxwell::ComparisonOp::Never_D3D:
|
||||||
case Maxwell::ComparisonOp::NeverOld:
|
case Maxwell::ComparisonOp::Never_GL:
|
||||||
return Shader::CompareFunction::Never;
|
return Shader::CompareFunction::Never;
|
||||||
case Maxwell::ComparisonOp::Less:
|
case Maxwell::ComparisonOp::Less_D3D:
|
||||||
case Maxwell::ComparisonOp::LessOld:
|
case Maxwell::ComparisonOp::Less_GL:
|
||||||
return Shader::CompareFunction::Less;
|
return Shader::CompareFunction::Less;
|
||||||
case Maxwell::ComparisonOp::Equal:
|
case Maxwell::ComparisonOp::Equal_D3D:
|
||||||
case Maxwell::ComparisonOp::EqualOld:
|
case Maxwell::ComparisonOp::Equal_GL:
|
||||||
return Shader::CompareFunction::Equal;
|
return Shader::CompareFunction::Equal;
|
||||||
case Maxwell::ComparisonOp::LessEqual:
|
case Maxwell::ComparisonOp::LessEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::LessEqualOld:
|
case Maxwell::ComparisonOp::LessEqual_GL:
|
||||||
return Shader::CompareFunction::LessThanEqual;
|
return Shader::CompareFunction::LessThanEqual;
|
||||||
case Maxwell::ComparisonOp::Greater:
|
case Maxwell::ComparisonOp::Greater_D3D:
|
||||||
case Maxwell::ComparisonOp::GreaterOld:
|
case Maxwell::ComparisonOp::Greater_GL:
|
||||||
return Shader::CompareFunction::Greater;
|
return Shader::CompareFunction::Greater;
|
||||||
case Maxwell::ComparisonOp::NotEqual:
|
case Maxwell::ComparisonOp::NotEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::NotEqualOld:
|
case Maxwell::ComparisonOp::NotEqual_GL:
|
||||||
return Shader::CompareFunction::NotEqual;
|
return Shader::CompareFunction::NotEqual;
|
||||||
case Maxwell::ComparisonOp::GreaterEqual:
|
case Maxwell::ComparisonOp::GreaterEqual_D3D:
|
||||||
case Maxwell::ComparisonOp::GreaterEqualOld:
|
case Maxwell::ComparisonOp::GreaterEqual_GL:
|
||||||
return Shader::CompareFunction::GreaterThanEqual;
|
return Shader::CompareFunction::GreaterThanEqual;
|
||||||
case Maxwell::ComparisonOp::Always:
|
case Maxwell::ComparisonOp::Always_D3D:
|
||||||
case Maxwell::ComparisonOp::AlwaysOld:
|
case Maxwell::ComparisonOp::Always_GL:
|
||||||
return Shader::CompareFunction::Always;
|
return Shader::CompareFunction::Always;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
|
UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
|
||||||
|
@ -96,15 +96,18 @@ Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribut
|
||||||
return Shader::AttributeType::Disabled;
|
return Shader::AttributeType::Disabled;
|
||||||
}
|
}
|
||||||
switch (attr.Type()) {
|
switch (attr.Type()) {
|
||||||
case Maxwell::VertexAttribute::Type::SignedNorm:
|
case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedNorm:
|
ASSERT_MSG(false, "Invalid vertex attribute type!");
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedScaled:
|
return Shader::AttributeType::Disabled;
|
||||||
case Maxwell::VertexAttribute::Type::SignedScaled:
|
case Maxwell::VertexAttribute::Type::SNorm:
|
||||||
|
case Maxwell::VertexAttribute::Type::UNorm:
|
||||||
|
case Maxwell::VertexAttribute::Type::UScaled:
|
||||||
|
case Maxwell::VertexAttribute::Type::SScaled:
|
||||||
case Maxwell::VertexAttribute::Type::Float:
|
case Maxwell::VertexAttribute::Type::Float:
|
||||||
return Shader::AttributeType::Float;
|
return Shader::AttributeType::Float;
|
||||||
case Maxwell::VertexAttribute::Type::SignedInt:
|
case Maxwell::VertexAttribute::Type::SInt:
|
||||||
return Shader::AttributeType::SignedInt;
|
return Shader::AttributeType::SignedInt;
|
||||||
case Maxwell::VertexAttribute::Type::UnsignedInt:
|
case Maxwell::VertexAttribute::Type::UInt:
|
||||||
return Shader::AttributeType::UnsignedInt;
|
return Shader::AttributeType::UnsignedInt;
|
||||||
}
|
}
|
||||||
return Shader::AttributeType::Float;
|
return Shader::AttributeType::Float;
|
||||||
|
@ -162,16 +165,14 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Shader::Stage::TessellationEval:
|
case Shader::Stage::TessellationEval:
|
||||||
// We have to flip tessellation clockwise for some reason...
|
|
||||||
info.tess_clockwise = key.state.tessellation_clockwise == 0;
|
|
||||||
info.tess_primitive = [&key] {
|
info.tess_primitive = [&key] {
|
||||||
const u32 raw{key.state.tessellation_primitive.Value()};
|
const u32 raw{key.state.tessellation_primitive.Value()};
|
||||||
switch (static_cast<Maxwell::TessellationPrimitive>(raw)) {
|
switch (static_cast<Maxwell::Tessellation::DomainType>(raw)) {
|
||||||
case Maxwell::TessellationPrimitive::Isolines:
|
case Maxwell::Tessellation::DomainType::Isolines:
|
||||||
return Shader::TessPrimitive::Isolines;
|
return Shader::TessPrimitive::Isolines;
|
||||||
case Maxwell::TessellationPrimitive::Triangles:
|
case Maxwell::Tessellation::DomainType::Triangles:
|
||||||
return Shader::TessPrimitive::Triangles;
|
return Shader::TessPrimitive::Triangles;
|
||||||
case Maxwell::TessellationPrimitive::Quads:
|
case Maxwell::Tessellation::DomainType::Quads:
|
||||||
return Shader::TessPrimitive::Quads;
|
return Shader::TessPrimitive::Quads;
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -179,12 +180,12 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
|
||||||
}();
|
}();
|
||||||
info.tess_spacing = [&] {
|
info.tess_spacing = [&] {
|
||||||
const u32 raw{key.state.tessellation_spacing};
|
const u32 raw{key.state.tessellation_spacing};
|
||||||
switch (static_cast<Maxwell::TessellationSpacing>(raw)) {
|
switch (static_cast<Maxwell::Tessellation::Spacing>(raw)) {
|
||||||
case Maxwell::TessellationSpacing::Equal:
|
case Maxwell::Tessellation::Spacing::Integer:
|
||||||
return Shader::TessSpacing::Equal;
|
return Shader::TessSpacing::Equal;
|
||||||
case Maxwell::TessellationSpacing::FractionalOdd:
|
case Maxwell::Tessellation::Spacing::FractionalOdd:
|
||||||
return Shader::TessSpacing::FractionalOdd;
|
return Shader::TessSpacing::FractionalOdd;
|
||||||
case Maxwell::TessellationSpacing::FractionalEven:
|
case Maxwell::Tessellation::Spacing::FractionalEven:
|
||||||
return Shader::TessSpacing::FractionalEven;
|
return Shader::TessSpacing::FractionalEven;
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -490,7 +491,7 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const
|
||||||
// If games are using a small index count, we can assume these are full screen quads.
|
// If games are using a small index count, we can assume these are full screen quads.
|
||||||
// Usually these shaders are only used once for building textures so we can assume they
|
// Usually these shaders are only used once for building textures so we can assume they
|
||||||
// can't be built async
|
// can't be built async
|
||||||
if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
|
if (maxwell3d->regs.index_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) {
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -70,7 +70,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
|
||||||
const float width = conv(src.scale_x * 2.0f);
|
const float width = conv(src.scale_x * 2.0f);
|
||||||
float y = conv(src.translate_y - src.scale_y);
|
float y = conv(src.translate_y - src.scale_y);
|
||||||
float height = conv(src.scale_y * 2.0f);
|
float height = conv(src.scale_y * 2.0f);
|
||||||
bool y_negate = regs.screen_y_control.y_negate;
|
bool y_negate = regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft;
|
||||||
|
|
||||||
if (!device.IsNvViewportSwizzleSupported()) {
|
if (!device.IsNvViewportSwizzleSupported()) {
|
||||||
y_negate = y_negate != (src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY);
|
y_negate = y_negate != (src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY);
|
||||||
|
@ -130,11 +130,11 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3
|
||||||
DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instanced,
|
DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instanced,
|
||||||
bool is_indexed) {
|
bool is_indexed) {
|
||||||
DrawParams params{
|
DrawParams params{
|
||||||
.base_instance = regs.vb_base_instance,
|
.base_instance = regs.global_base_instance_index,
|
||||||
.num_instances = is_instanced ? num_instances : 1,
|
.num_instances = is_instanced ? num_instances : 1,
|
||||||
.base_vertex = is_indexed ? regs.vb_element_base : regs.vertex_buffer.first,
|
.base_vertex = is_indexed ? regs.global_base_vertex_index : regs.vertex_buffer.first,
|
||||||
.num_vertices = is_indexed ? regs.index_array.count : regs.vertex_buffer.count,
|
.num_vertices = is_indexed ? regs.index_buffer.count : regs.vertex_buffer.count,
|
||||||
.first_index = is_indexed ? regs.index_array.first : 0,
|
.first_index = is_indexed ? regs.index_buffer.first : 0,
|
||||||
.is_indexed = is_indexed,
|
.is_indexed = is_indexed,
|
||||||
};
|
};
|
||||||
if (regs.draw.topology == Maxwell::PrimitiveTopology::Quads) {
|
if (regs.draw.topology == Maxwell::PrimitiveTopology::Quads) {
|
||||||
|
@ -225,10 +225,10 @@ void RasterizerVulkan::Clear() {
|
||||||
query_cache.UpdateCounters();
|
query_cache.UpdateCounters();
|
||||||
|
|
||||||
auto& regs = maxwell3d->regs;
|
auto& regs = maxwell3d->regs;
|
||||||
const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
const bool use_color = regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
|
||||||
regs.clear_buffers.A;
|
regs.clear_surface.A;
|
||||||
const bool use_depth = regs.clear_buffers.Z;
|
const bool use_depth = regs.clear_surface.Z;
|
||||||
const bool use_stencil = regs.clear_buffers.S;
|
const bool use_stencil = regs.clear_surface.S;
|
||||||
if (!use_color && !use_depth && !use_stencil) {
|
if (!use_color && !use_depth && !use_stencil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -254,9 +254,9 @@ void RasterizerVulkan::Clear() {
|
||||||
default_scissor.extent.height = std::numeric_limits<s32>::max();
|
default_scissor.extent.height = std::numeric_limits<s32>::max();
|
||||||
|
|
||||||
VkClearRect clear_rect{
|
VkClearRect clear_rect{
|
||||||
.rect = regs.clear_flags.scissor ? GetScissorState(regs, 0, up_scale, down_shift)
|
.rect = regs.clear_control.use_scissor ? GetScissorState(regs, 0, up_scale, down_shift)
|
||||||
: default_scissor,
|
: default_scissor,
|
||||||
.baseArrayLayer = regs.clear_buffers.layer,
|
.baseArrayLayer = regs.clear_surface.layer,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
if (clear_rect.rect.extent.width == 0 || clear_rect.rect.extent.height == 0) {
|
if (clear_rect.rect.extent.width == 0 || clear_rect.rect.extent.height == 0) {
|
||||||
|
@ -267,7 +267,7 @@ void RasterizerVulkan::Clear() {
|
||||||
.height = std::min(clear_rect.rect.extent.height, render_area.height),
|
.height = std::min(clear_rect.rect.extent.height, render_area.height),
|
||||||
};
|
};
|
||||||
|
|
||||||
const u32 color_attachment = regs.clear_buffers.RT;
|
const u32 color_attachment = regs.clear_surface.RT;
|
||||||
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
|
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
|
||||||
VkClearValue clear_value;
|
VkClearValue clear_value;
|
||||||
bool is_integer = false;
|
bool is_integer = false;
|
||||||
|
@ -289,7 +289,8 @@ void RasterizerVulkan::Clear() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!is_integer) {
|
if (!is_integer) {
|
||||||
std::memcpy(clear_value.color.float32, regs.clear_color, sizeof(regs.clear_color));
|
std::memcpy(clear_value.color.float32, regs.clear_color.data(),
|
||||||
|
regs.clear_color.size() * sizeof(f32));
|
||||||
} else if (!is_signed) {
|
} else if (!is_signed) {
|
||||||
for (size_t i = 0; i < 4; i++) {
|
for (size_t i = 0; i < 4; i++) {
|
||||||
clear_value.color.uint32[i] = static_cast<u32>(
|
clear_value.color.uint32[i] = static_cast<u32>(
|
||||||
|
@ -648,23 +649,23 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||||
|
|
||||||
void RasterizerVulkan::BeginTransformFeedback() {
|
void RasterizerVulkan::BeginTransformFeedback() {
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
if (regs.tfb_enabled == 0) {
|
if (regs.transform_feedback_enabled == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!device.IsExtTransformFeedbackSupported()) {
|
if (!device.IsExtTransformFeedbackSupported()) {
|
||||||
LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported");
|
LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) ||
|
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
|
||||||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) ||
|
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) ||
|
||||||
regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry));
|
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry));
|
||||||
scheduler.Record(
|
scheduler.Record(
|
||||||
[](vk::CommandBuffer cmdbuf) { cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); });
|
[](vk::CommandBuffer cmdbuf) { cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::EndTransformFeedback() {
|
void RasterizerVulkan::EndTransformFeedback() {
|
||||||
const auto& regs = maxwell3d->regs;
|
const auto& regs = maxwell3d->regs;
|
||||||
if (regs.tfb_enabled == 0) {
|
if (regs.transform_feedback_enabled == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!device.IsExtTransformFeedbackSupported()) {
|
if (!device.IsExtTransformFeedbackSupported()) {
|
||||||
|
@ -728,11 +729,11 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
if (!state_tracker.TouchDepthBias()) {
|
if (!state_tracker.TouchDepthBias()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float units = regs.polygon_offset_units / 2.0f;
|
float units = regs.depth_bias / 2.0f;
|
||||||
const bool is_d24 = regs.zeta.format == Tegra::DepthFormat::S8_UINT_Z24_UNORM ||
|
const bool is_d24 = regs.zeta.format == Tegra::DepthFormat::Z24_UNORM_S8_UINT ||
|
||||||
regs.zeta.format == Tegra::DepthFormat::D24X8_UNORM ||
|
regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM ||
|
||||||
regs.zeta.format == Tegra::DepthFormat::D24S8_UNORM ||
|
regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM ||
|
||||||
regs.zeta.format == Tegra::DepthFormat::D24C8_UNORM;
|
regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM;
|
||||||
if (is_d24 && !device.SupportsD24DepthBuffer()) {
|
if (is_d24 && !device.SupportsD24DepthBuffer()) {
|
||||||
// the base formulas can be obtained from here:
|
// the base formulas can be obtained from here:
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
|
// https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
|
||||||
|
@ -740,8 +741,8 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
|
static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
|
||||||
units = static_cast<float>(static_cast<double>(units) * rescale_factor);
|
units = static_cast<float>(static_cast<double>(units) * rescale_factor);
|
||||||
}
|
}
|
||||||
scheduler.Record([constant = units, clamp = regs.polygon_offset_clamp,
|
scheduler.Record([constant = units, clamp = regs.depth_bias_clamp,
|
||||||
factor = regs.polygon_offset_factor](vk::CommandBuffer cmdbuf) {
|
factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.SetDepthBias(constant, clamp, factor);
|
cmdbuf.SetDepthBias(constant, clamp, factor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -771,10 +772,11 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
|
||||||
if (regs.stencil_two_side_enable) {
|
if (regs.stencil_two_side_enable) {
|
||||||
// Separate values per face
|
// Separate values per face
|
||||||
scheduler.Record(
|
scheduler.Record(
|
||||||
[front_ref = regs.stencil_front_func_ref, front_write_mask = regs.stencil_front_mask,
|
[front_ref = regs.stencil_front_func.ref,
|
||||||
front_test_mask = regs.stencil_front_func_mask, back_ref = regs.stencil_back_func_ref,
|
front_write_mask = regs.stencil_front_func.mask,
|
||||||
back_write_mask = regs.stencil_back_mask,
|
front_test_mask = regs.stencil_front_func.func_mask,
|
||||||
back_test_mask = regs.stencil_back_func_mask](vk::CommandBuffer cmdbuf) {
|
back_ref = regs.stencil_back_func.ref, back_write_mask = regs.stencil_back_func.mask,
|
||||||
|
back_test_mask = regs.stencil_back_func.func_mask](vk::CommandBuffer cmdbuf) {
|
||||||
// Front face
|
// Front face
|
||||||
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_BIT, front_ref);
|
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_BIT, front_ref);
|
||||||
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_BIT, front_write_mask);
|
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_BIT, front_write_mask);
|
||||||
|
@ -787,8 +789,9 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Front face defines both faces
|
// Front face defines both faces
|
||||||
scheduler.Record([ref = regs.stencil_front_func_ref, write_mask = regs.stencil_front_mask,
|
scheduler.Record([ref = regs.stencil_front_func.ref,
|
||||||
test_mask = regs.stencil_front_func_mask](vk::CommandBuffer cmdbuf) {
|
write_mask = regs.stencil_front_func.mask,
|
||||||
|
test_mask = regs.stencil_front_func.func_mask](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, ref);
|
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, ref);
|
||||||
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_AND_BACK, write_mask);
|
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_AND_BACK, write_mask);
|
||||||
cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_AND_BACK, test_mask);
|
cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_AND_BACK, test_mask);
|
||||||
|
@ -800,7 +803,8 @@ void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
if (!state_tracker.TouchLineWidth()) {
|
if (!state_tracker.TouchLineWidth()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const float width = regs.line_smooth_enable ? regs.line_width_smooth : regs.line_width_aliased;
|
const float width =
|
||||||
|
regs.line_anti_alias_enable ? regs.line_width_smooth : regs.line_width_aliased;
|
||||||
scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); });
|
scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,8 +812,8 @@ void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
if (!state_tracker.TouchCullMode()) {
|
if (!state_tracker.TouchCullMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scheduler.Record(
|
scheduler.Record([enabled = regs.gl_cull_test_enabled,
|
||||||
[enabled = regs.cull_test_enabled, cull_face = regs.cull_face](vk::CommandBuffer cmdbuf) {
|
cull_face = regs.gl_cull_face](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.SetCullModeEXT(enabled ? MaxwellToVK::CullFace(cull_face) : VK_CULL_MODE_NONE);
|
cmdbuf.SetCullModeEXT(enabled ? MaxwellToVK::CullFace(cull_face) : VK_CULL_MODE_NONE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -860,8 +864,8 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkFrontFace front_face = MaxwellToVK::FrontFace(regs.front_face);
|
VkFrontFace front_face = MaxwellToVK::FrontFace(regs.gl_front_face);
|
||||||
if (regs.screen_y_control.triangle_rast_flip != 0) {
|
if (regs.window_origin.flip_y != 0) {
|
||||||
front_face = front_face == VK_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_COUNTER_CLOCKWISE
|
front_face = front_face == VK_FRONT_FACE_CLOCKWISE ? VK_FRONT_FACE_COUNTER_CLOCKWISE
|
||||||
: VK_FRONT_FACE_CLOCKWISE;
|
: VK_FRONT_FACE_CLOCKWISE;
|
||||||
}
|
}
|
||||||
|
@ -873,16 +877,16 @@ void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
if (!state_tracker.TouchStencilOp()) {
|
if (!state_tracker.TouchStencilOp()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Maxwell::StencilOp fail = regs.stencil_front_op_fail;
|
const Maxwell::StencilOp::Op fail = regs.stencil_front_op.fail;
|
||||||
const Maxwell::StencilOp zfail = regs.stencil_front_op_zfail;
|
const Maxwell::StencilOp::Op zfail = regs.stencil_front_op.zfail;
|
||||||
const Maxwell::StencilOp zpass = regs.stencil_front_op_zpass;
|
const Maxwell::StencilOp::Op zpass = regs.stencil_front_op.zpass;
|
||||||
const Maxwell::ComparisonOp compare = regs.stencil_front_func_func;
|
const Maxwell::ComparisonOp compare = regs.stencil_front_op.func;
|
||||||
if (regs.stencil_two_side_enable) {
|
if (regs.stencil_two_side_enable) {
|
||||||
// Separate stencil op per face
|
// Separate stencil op per face
|
||||||
const Maxwell::StencilOp back_fail = regs.stencil_back_op_fail;
|
const Maxwell::StencilOp::Op back_fail = regs.stencil_back_op.fail;
|
||||||
const Maxwell::StencilOp back_zfail = regs.stencil_back_op_zfail;
|
const Maxwell::StencilOp::Op back_zfail = regs.stencil_back_op.zfail;
|
||||||
const Maxwell::StencilOp back_zpass = regs.stencil_back_op_zpass;
|
const Maxwell::StencilOp::Op back_zpass = regs.stencil_back_op.zpass;
|
||||||
const Maxwell::ComparisonOp back_compare = regs.stencil_back_func_func;
|
const Maxwell::ComparisonOp back_compare = regs.stencil_back_op.func;
|
||||||
scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass,
|
scheduler.Record([fail, zfail, zpass, compare, back_fail, back_zfail, back_zpass,
|
||||||
back_compare](vk::CommandBuffer cmdbuf) {
|
back_compare](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail),
|
cmdbuf.SetStencilOpEXT(VK_STENCIL_FACE_FRONT_BIT, MaxwellToVK::StencilOp(fail),
|
||||||
|
@ -954,15 +958,15 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
|
||||||
dirty[Dirty::VertexBinding0 + index] = false;
|
dirty[Dirty::VertexBinding0 + index] = false;
|
||||||
|
|
||||||
const u32 binding{static_cast<u32>(index)};
|
const u32 binding{static_cast<u32>(index)};
|
||||||
const auto& input_binding{regs.vertex_array[binding]};
|
const auto& input_binding{regs.vertex_streams[binding]};
|
||||||
const bool is_instanced{regs.instanced_arrays.IsInstancingEnabled(binding)};
|
const bool is_instanced{regs.vertex_stream_instances.IsInstancingEnabled(binding)};
|
||||||
bindings.push_back({
|
bindings.push_back({
|
||||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
|
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.binding = binding,
|
.binding = binding,
|
||||||
.stride = input_binding.stride,
|
.stride = input_binding.stride,
|
||||||
.inputRate = is_instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
|
.inputRate = is_instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
|
||||||
.divisor = is_instanced ? input_binding.divisor : 1,
|
.divisor = is_instanced ? input_binding.frequency : 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {
|
||||||
|
|
|
@ -51,8 +51,8 @@ Flags MakeInvalidationFlags() {
|
||||||
void SetupDirtyViewports(Tables& tables) {
|
void SetupDirtyViewports(Tables& tables) {
|
||||||
FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
|
FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
|
||||||
FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
|
FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
|
||||||
tables[0][OFF(viewport_transform_enabled)] = Viewports;
|
tables[0][OFF(viewport_scale_offset_enbled)] = Viewports;
|
||||||
tables[1][OFF(screen_y_control)] = Viewports;
|
tables[1][OFF(window_origin)] = Viewports;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyScissors(Tables& tables) {
|
void SetupDirtyScissors(Tables& tables) {
|
||||||
|
@ -61,9 +61,9 @@ void SetupDirtyScissors(Tables& tables) {
|
||||||
|
|
||||||
void SetupDirtyDepthBias(Tables& tables) {
|
void SetupDirtyDepthBias(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
table[OFF(polygon_offset_units)] = DepthBias;
|
table[OFF(depth_bias)] = DepthBias;
|
||||||
table[OFF(polygon_offset_clamp)] = DepthBias;
|
table[OFF(depth_bias_clamp)] = DepthBias;
|
||||||
table[OFF(polygon_offset_factor)] = DepthBias;
|
table[OFF(slope_scale_depth_bias)] = DepthBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyBlendConstants(Tables& tables) {
|
void SetupDirtyBlendConstants(Tables& tables) {
|
||||||
|
@ -77,12 +77,12 @@ void SetupDirtyDepthBounds(Tables& tables) {
|
||||||
void SetupDirtyStencilProperties(Tables& tables) {
|
void SetupDirtyStencilProperties(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
table[OFF(stencil_two_side_enable)] = StencilProperties;
|
table[OFF(stencil_two_side_enable)] = StencilProperties;
|
||||||
table[OFF(stencil_front_func_ref)] = StencilProperties;
|
table[OFF(stencil_front_func.ref)] = StencilProperties;
|
||||||
table[OFF(stencil_front_mask)] = StencilProperties;
|
table[OFF(stencil_front_func.mask)] = StencilProperties;
|
||||||
table[OFF(stencil_front_func_mask)] = StencilProperties;
|
table[OFF(stencil_front_func.func_mask)] = StencilProperties;
|
||||||
table[OFF(stencil_back_func_ref)] = StencilProperties;
|
table[OFF(stencil_back_func.ref)] = StencilProperties;
|
||||||
table[OFF(stencil_back_mask)] = StencilProperties;
|
table[OFF(stencil_back_func.mask)] = StencilProperties;
|
||||||
table[OFF(stencil_back_func_mask)] = StencilProperties;
|
table[OFF(stencil_back_func.func_mask)] = StencilProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyLineWidth(Tables& tables) {
|
void SetupDirtyLineWidth(Tables& tables) {
|
||||||
|
@ -92,8 +92,8 @@ void SetupDirtyLineWidth(Tables& tables) {
|
||||||
|
|
||||||
void SetupDirtyCullMode(Tables& tables) {
|
void SetupDirtyCullMode(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
table[OFF(cull_face)] = CullMode;
|
table[OFF(gl_cull_face)] = CullMode;
|
||||||
table[OFF(cull_test_enabled)] = CullMode;
|
table[OFF(gl_cull_test_enabled)] = CullMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyDepthBoundsEnable(Tables& tables) {
|
void SetupDirtyDepthBoundsEnable(Tables& tables) {
|
||||||
|
@ -114,20 +114,20 @@ void SetupDirtyDepthCompareOp(Tables& tables) {
|
||||||
|
|
||||||
void SetupDirtyFrontFace(Tables& tables) {
|
void SetupDirtyFrontFace(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
table[OFF(front_face)] = FrontFace;
|
table[OFF(gl_front_face)] = FrontFace;
|
||||||
table[OFF(screen_y_control)] = FrontFace;
|
table[OFF(window_origin)] = FrontFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyStencilOp(Tables& tables) {
|
void SetupDirtyStencilOp(Tables& tables) {
|
||||||
auto& table = tables[0];
|
auto& table = tables[0];
|
||||||
table[OFF(stencil_front_op_fail)] = StencilOp;
|
table[OFF(stencil_front_op.fail)] = StencilOp;
|
||||||
table[OFF(stencil_front_op_zfail)] = StencilOp;
|
table[OFF(stencil_front_op.zfail)] = StencilOp;
|
||||||
table[OFF(stencil_front_op_zpass)] = StencilOp;
|
table[OFF(stencil_front_op.zpass)] = StencilOp;
|
||||||
table[OFF(stencil_front_func_func)] = StencilOp;
|
table[OFF(stencil_front_op.func)] = StencilOp;
|
||||||
table[OFF(stencil_back_op_fail)] = StencilOp;
|
table[OFF(stencil_back_op.fail)] = StencilOp;
|
||||||
table[OFF(stencil_back_op_zfail)] = StencilOp;
|
table[OFF(stencil_back_op.zfail)] = StencilOp;
|
||||||
table[OFF(stencil_back_op_zpass)] = StencilOp;
|
table[OFF(stencil_back_op.zpass)] = StencilOp;
|
||||||
table[OFF(stencil_back_func_func)] = StencilOp;
|
table[OFF(stencil_back_op.func)] = StencilOp;
|
||||||
|
|
||||||
// Table 0 is used by StencilProperties
|
// Table 0 is used by StencilProperties
|
||||||
tables[1][OFF(stencil_two_side_enable)] = StencilOp;
|
tables[1][OFF(stencil_two_side_enable)] = StencilOp;
|
||||||
|
@ -139,10 +139,10 @@ void SetupDirtyStencilTestEnable(Tables& tables) {
|
||||||
|
|
||||||
void SetupDirtyBlending(Tables& tables) {
|
void SetupDirtyBlending(Tables& tables) {
|
||||||
tables[0][OFF(color_mask_common)] = Blending;
|
tables[0][OFF(color_mask_common)] = Blending;
|
||||||
tables[0][OFF(independent_blend_enable)] = Blending;
|
tables[0][OFF(blend_per_target_enabled)] = Blending;
|
||||||
FillBlock(tables[0], OFF(color_mask), NUM(color_mask), Blending);
|
FillBlock(tables[0], OFF(color_mask), NUM(color_mask), Blending);
|
||||||
FillBlock(tables[0], OFF(blend), NUM(blend), Blending);
|
FillBlock(tables[0], OFF(blend), NUM(blend), Blending);
|
||||||
FillBlock(tables[0], OFF(independent_blend), NUM(independent_blend), Blending);
|
FillBlock(tables[0], OFF(blend_per_target), NUM(blend_per_target), Blending);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupDirtyViewportSwizzles(Tables& tables) {
|
void SetupDirtyViewportSwizzles(Tables& tables) {
|
||||||
|
@ -166,10 +166,10 @@ void SetupDirtyVertexBindings(Tables& tables) {
|
||||||
static constexpr size_t divisor_offset = 3;
|
static constexpr size_t divisor_offset = 3;
|
||||||
for (size_t i = 0; i < Regs::NumVertexArrays; ++i) {
|
for (size_t i = 0; i < Regs::NumVertexArrays; ++i) {
|
||||||
const u8 flag = static_cast<u8>(VertexBinding0 + i);
|
const u8 flag = static_cast<u8>(VertexBinding0 + i);
|
||||||
tables[0][OFF(instanced_arrays) + i] = VertexInput;
|
tables[0][OFF(vertex_stream_instances) + i] = VertexInput;
|
||||||
tables[1][OFF(instanced_arrays) + i] = flag;
|
tables[1][OFF(vertex_stream_instances) + i] = flag;
|
||||||
tables[0][OFF(vertex_array) + i * NUM(vertex_array[0]) + divisor_offset] = VertexInput;
|
tables[0][OFF(vertex_streams) + i * NUM(vertex_streams[0]) + divisor_offset] = VertexInput;
|
||||||
tables[1][OFF(vertex_array) + i * NUM(vertex_array[0]) + divisor_offset] = flag;
|
tables[1][OFF(vertex_streams) + i * NUM(vertex_streams[0]) + divisor_offset] = flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
|
@ -43,14 +43,14 @@ bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) {
|
||||||
}
|
}
|
||||||
dirty[VideoCommon::Dirty::Shaders] = false;
|
dirty[VideoCommon::Dirty::Shaders] = false;
|
||||||
|
|
||||||
const GPUVAddr base_addr{maxwell3d->regs.code_address.CodeAddress()};
|
const GPUVAddr base_addr{maxwell3d->regs.program_region.Address()};
|
||||||
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram; ++index) {
|
for (size_t index = 0; index < Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram; ++index) {
|
||||||
if (!maxwell3d->regs.IsShaderConfigEnabled(index)) {
|
if (!maxwell3d->regs.IsShaderConfigEnabled(index)) {
|
||||||
unique_hashes[index] = 0;
|
unique_hashes[index] = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& shader_config{maxwell3d->regs.shader_config[index]};
|
const auto& shader_config{maxwell3d->regs.pipelines[index]};
|
||||||
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderProgram>(index)};
|
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)};
|
||||||
const GPUVAddr shader_addr{base_addr + shader_config.offset};
|
const GPUVAddr shader_addr{base_addr + shader_config.offset};
|
||||||
const std::optional<VAddr> cpu_shader_addr{gpu_memory->GpuToCpuAddress(shader_addr)};
|
const std::optional<VAddr> cpu_shader_addr{gpu_memory->GpuToCpuAddress(shader_addr)};
|
||||||
if (!cpu_shader_addr) {
|
if (!cpu_shader_addr) {
|
||||||
|
@ -90,14 +90,14 @@ const ShaderInfo* ShaderCache::ComputeShader() {
|
||||||
void ShaderCache::GetGraphicsEnvironments(GraphicsEnvironments& result,
|
void ShaderCache::GetGraphicsEnvironments(GraphicsEnvironments& result,
|
||||||
const std::array<u64, NUM_PROGRAMS>& unique_hashes) {
|
const std::array<u64, NUM_PROGRAMS>& unique_hashes) {
|
||||||
size_t env_index{};
|
size_t env_index{};
|
||||||
const GPUVAddr base_addr{maxwell3d->regs.code_address.CodeAddress()};
|
const GPUVAddr base_addr{maxwell3d->regs.program_region.Address()};
|
||||||
for (size_t index = 0; index < NUM_PROGRAMS; ++index) {
|
for (size_t index = 0; index < NUM_PROGRAMS; ++index) {
|
||||||
if (unique_hashes[index] == 0) {
|
if (unique_hashes[index] == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderProgram>(index)};
|
const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)};
|
||||||
auto& env{result.envs[index]};
|
auto& env{result.envs[index]};
|
||||||
const u32 start_address{maxwell3d->regs.shader_config[index].offset};
|
const u32 start_address{maxwell3d->regs.pipelines[index].offset};
|
||||||
env = GraphicsEnvironment{*maxwell3d, *gpu_memory, program, base_addr, start_address};
|
env = GraphicsEnvironment{*maxwell3d, *gpu_memory, program, base_addr, start_address};
|
||||||
env.SetCachedSize(shader_infos[index]->size_bytes);
|
env.SetCachedSize(shader_infos[index]->size_bytes);
|
||||||
result.env_ptrs[env_index++] = &env;
|
result.env_ptrs[env_index++] = &env;
|
||||||
|
|
|
@ -250,34 +250,34 @@ Shader::TextureType GenericEnvironment::ReadTextureTypeImpl(GPUVAddr tic_addr, u
|
||||||
|
|
||||||
GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
|
GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
|
||||||
Tegra::MemoryManager& gpu_memory_,
|
Tegra::MemoryManager& gpu_memory_,
|
||||||
Maxwell::ShaderProgram program, GPUVAddr program_base_,
|
Maxwell::ShaderType program, GPUVAddr program_base_,
|
||||||
u32 start_address_)
|
u32 start_address_)
|
||||||
: GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} {
|
: GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} {
|
||||||
gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph));
|
gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph));
|
||||||
initial_offset = sizeof(sph);
|
initial_offset = sizeof(sph);
|
||||||
gp_passthrough_mask = maxwell3d->regs.gp_passthrough_mask;
|
gp_passthrough_mask = maxwell3d->regs.post_vtg_shader_attrib_skip_mask;
|
||||||
switch (program) {
|
switch (program) {
|
||||||
case Maxwell::ShaderProgram::VertexA:
|
case Maxwell::ShaderType::VertexA:
|
||||||
stage = Shader::Stage::VertexA;
|
stage = Shader::Stage::VertexA;
|
||||||
stage_index = 0;
|
stage_index = 0;
|
||||||
break;
|
break;
|
||||||
case Maxwell::ShaderProgram::VertexB:
|
case Maxwell::ShaderType::VertexB:
|
||||||
stage = Shader::Stage::VertexB;
|
stage = Shader::Stage::VertexB;
|
||||||
stage_index = 0;
|
stage_index = 0;
|
||||||
break;
|
break;
|
||||||
case Maxwell::ShaderProgram::TesselationControl:
|
case Maxwell::ShaderType::TessellationInit:
|
||||||
stage = Shader::Stage::TessellationControl;
|
stage = Shader::Stage::TessellationControl;
|
||||||
stage_index = 1;
|
stage_index = 1;
|
||||||
break;
|
break;
|
||||||
case Maxwell::ShaderProgram::TesselationEval:
|
case Maxwell::ShaderType::Tessellation:
|
||||||
stage = Shader::Stage::TessellationEval;
|
stage = Shader::Stage::TessellationEval;
|
||||||
stage_index = 2;
|
stage_index = 2;
|
||||||
break;
|
break;
|
||||||
case Maxwell::ShaderProgram::Geometry:
|
case Maxwell::ShaderType::Geometry:
|
||||||
stage = Shader::Stage::Geometry;
|
stage = Shader::Stage::Geometry;
|
||||||
stage_index = 3;
|
stage_index = 3;
|
||||||
break;
|
break;
|
||||||
case Maxwell::ShaderProgram::Fragment:
|
case Maxwell::ShaderType::Pixel:
|
||||||
stage = Shader::Stage::Fragment;
|
stage = Shader::Stage::Fragment;
|
||||||
stage_index = 4;
|
stage_index = 4;
|
||||||
break;
|
break;
|
||||||
|
@ -288,7 +288,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
|
||||||
const u64 local_size{sph.LocalMemorySize()};
|
const u64 local_size{sph.LocalMemorySize()};
|
||||||
ASSERT(local_size <= std::numeric_limits<u32>::max());
|
ASSERT(local_size <= std::numeric_limits<u32>::max());
|
||||||
local_memory_size = static_cast<u32>(local_size) + sph.common3.shader_local_memory_crs_size;
|
local_memory_size = static_cast<u32>(local_size) + sph.common3.shader_local_memory_crs_size;
|
||||||
texture_bound = maxwell3d->regs.tex_cb_index;
|
texture_bound = maxwell3d->regs.bindless_texture_const_buffer_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
|
u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
|
||||||
|
@ -304,8 +304,9 @@ u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
|
||||||
|
|
||||||
Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) {
|
Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) {
|
||||||
const auto& regs{maxwell3d->regs};
|
const auto& regs{maxwell3d->regs};
|
||||||
const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
|
const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
|
||||||
return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, via_header_index, handle);
|
return ReadTextureTypeImpl(regs.tex_header.Address(), regs.tex_header.limit, via_header_index,
|
||||||
|
handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_,
|
ComputeEnvironment::ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_,
|
||||||
|
|
|
@ -93,7 +93,7 @@ public:
|
||||||
explicit GraphicsEnvironment() = default;
|
explicit GraphicsEnvironment() = default;
|
||||||
explicit GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
|
explicit GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
|
||||||
Tegra::MemoryManager& gpu_memory_,
|
Tegra::MemoryManager& gpu_memory_,
|
||||||
Tegra::Engines::Maxwell3D::Regs::ShaderProgram program,
|
Tegra::Engines::Maxwell3D::Regs::ShaderType program,
|
||||||
GPUVAddr program_base_, u32 start_address_);
|
GPUVAddr program_base_, u32 start_address_);
|
||||||
|
|
||||||
~GraphicsEnvironment() override = default;
|
~GraphicsEnvironment() override = default;
|
||||||
|
|
|
@ -73,17 +73,17 @@ bool SurfaceTargetIsArray(SurfaceTarget target) {
|
||||||
|
|
||||||
PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
|
PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case Tegra::DepthFormat::S8_UINT_Z24_UNORM:
|
case Tegra::DepthFormat::Z24_UNORM_S8_UINT:
|
||||||
return PixelFormat::S8_UINT_D24_UNORM;
|
return PixelFormat::S8_UINT_D24_UNORM;
|
||||||
case Tegra::DepthFormat::D24S8_UNORM:
|
case Tegra::DepthFormat::S8Z24_UNORM:
|
||||||
return PixelFormat::D24_UNORM_S8_UINT;
|
return PixelFormat::D24_UNORM_S8_UINT;
|
||||||
case Tegra::DepthFormat::D32_FLOAT:
|
case Tegra::DepthFormat::Z32_FLOAT:
|
||||||
return PixelFormat::D32_FLOAT;
|
return PixelFormat::D32_FLOAT;
|
||||||
case Tegra::DepthFormat::D16_UNORM:
|
case Tegra::DepthFormat::Z16_UNORM:
|
||||||
return PixelFormat::D16_UNORM;
|
return PixelFormat::D16_UNORM;
|
||||||
case Tegra::DepthFormat::S8_UINT:
|
case Tegra::DepthFormat::S8_UINT:
|
||||||
return PixelFormat::S8_UINT;
|
return PixelFormat::S8_UINT;
|
||||||
case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT:
|
case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT:
|
||||||
return PixelFormat::D32_FLOAT_S8_UINT;
|
return PixelFormat::D32_FLOAT_S8_UINT;
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
|
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
|
||||||
|
@ -117,9 +117,9 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
|
||||||
return PixelFormat::R32G32_UINT;
|
return PixelFormat::R32G32_UINT;
|
||||||
case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
|
case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
|
||||||
return PixelFormat::R16G16B16X16_FLOAT;
|
return PixelFormat::R16G16B16X16_FLOAT;
|
||||||
case Tegra::RenderTargetFormat::B8G8R8A8_UNORM:
|
case Tegra::RenderTargetFormat::A8R8G8B8_UNORM:
|
||||||
return PixelFormat::B8G8R8A8_UNORM;
|
return PixelFormat::B8G8R8A8_UNORM;
|
||||||
case Tegra::RenderTargetFormat::B8G8R8A8_SRGB:
|
case Tegra::RenderTargetFormat::A8R8G8B8_SRGB:
|
||||||
return PixelFormat::B8G8R8A8_SRGB;
|
return PixelFormat::B8G8R8A8_SRGB;
|
||||||
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
|
case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
|
||||||
return PixelFormat::A2B10G10R10_UNORM;
|
return PixelFormat::A2B10G10R10_UNORM;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "video_core/surface.h"
|
#include "video_core/surface.h"
|
||||||
#include "video_core/texture_cache/format_lookup_table.h"
|
#include "video_core/texture_cache/format_lookup_table.h"
|
||||||
|
@ -12,6 +14,7 @@
|
||||||
|
|
||||||
namespace VideoCommon {
|
namespace VideoCommon {
|
||||||
|
|
||||||
|
using Tegra::Engines::Maxwell3D;
|
||||||
using Tegra::Texture::TextureType;
|
using Tegra::Texture::TextureType;
|
||||||
using Tegra::Texture::TICEntry;
|
using Tegra::Texture::TICEntry;
|
||||||
using VideoCore::Surface::PixelFormat;
|
using VideoCore::Surface::PixelFormat;
|
||||||
|
@ -107,12 +110,13 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept {
|
ImageInfo::ImageInfo(const Maxwell3D::Regs& regs, size_t index) noexcept {
|
||||||
const auto& rt = regs.rt[index];
|
const auto& rt = regs.rt[index];
|
||||||
format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format);
|
format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format);
|
||||||
rescaleable = false;
|
rescaleable = false;
|
||||||
if (rt.tile_mode.is_pitch_linear) {
|
if (rt.tile_mode.is_pitch_linear) {
|
||||||
ASSERT(rt.tile_mode.is_3d == 0);
|
ASSERT(rt.tile_mode.dim_control ==
|
||||||
|
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesArray);
|
||||||
type = ImageType::Linear;
|
type = ImageType::Linear;
|
||||||
pitch = rt.width;
|
pitch = rt.width;
|
||||||
size = Extent3D{
|
size = Extent3D{
|
||||||
|
@ -124,15 +128,16 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index)
|
||||||
}
|
}
|
||||||
size.width = rt.width;
|
size.width = rt.width;
|
||||||
size.height = rt.height;
|
size.height = rt.height;
|
||||||
layer_stride = rt.layer_stride * 4;
|
layer_stride = rt.array_pitch * 4;
|
||||||
maybe_unaligned_layer_stride = layer_stride;
|
maybe_unaligned_layer_stride = layer_stride;
|
||||||
num_samples = NumSamples(regs.multisample_mode);
|
num_samples = NumSamples(regs.anti_alias_samples_mode);
|
||||||
block = Extent3D{
|
block = Extent3D{
|
||||||
.width = rt.tile_mode.block_width,
|
.width = rt.tile_mode.block_width,
|
||||||
.height = rt.tile_mode.block_height,
|
.height = rt.tile_mode.block_height,
|
||||||
.depth = rt.tile_mode.block_depth,
|
.depth = rt.tile_mode.block_depth,
|
||||||
};
|
};
|
||||||
if (rt.tile_mode.is_3d) {
|
if (rt.tile_mode.dim_control ==
|
||||||
|
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesDepth) {
|
||||||
type = ImageType::e3D;
|
type = ImageType::e3D;
|
||||||
size.depth = rt.depth;
|
size.depth = rt.depth;
|
||||||
} else {
|
} else {
|
||||||
|
@ -146,31 +151,37 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index)
|
||||||
|
|
||||||
ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
|
ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
|
||||||
format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format);
|
format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format);
|
||||||
size.width = regs.zeta_width;
|
size.width = regs.zeta_size.width;
|
||||||
size.height = regs.zeta_height;
|
size.height = regs.zeta_size.height;
|
||||||
rescaleable = false;
|
rescaleable = false;
|
||||||
resources.levels = 1;
|
resources.levels = 1;
|
||||||
layer_stride = regs.zeta.layer_stride * 4;
|
layer_stride = regs.zeta.array_pitch * 4;
|
||||||
maybe_unaligned_layer_stride = layer_stride;
|
maybe_unaligned_layer_stride = layer_stride;
|
||||||
num_samples = NumSamples(regs.multisample_mode);
|
num_samples = NumSamples(regs.anti_alias_samples_mode);
|
||||||
block = Extent3D{
|
block = Extent3D{
|
||||||
.width = regs.zeta.tile_mode.block_width,
|
.width = regs.zeta.tile_mode.block_width,
|
||||||
.height = regs.zeta.tile_mode.block_height,
|
.height = regs.zeta.tile_mode.block_height,
|
||||||
.depth = regs.zeta.tile_mode.block_depth,
|
.depth = regs.zeta.tile_mode.block_depth,
|
||||||
};
|
};
|
||||||
if (regs.zeta.tile_mode.is_pitch_linear) {
|
if (regs.zeta.tile_mode.is_pitch_linear) {
|
||||||
ASSERT(regs.zeta.tile_mode.is_3d == 0);
|
ASSERT(regs.zeta.tile_mode.dim_control ==
|
||||||
|
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesArray);
|
||||||
type = ImageType::Linear;
|
type = ImageType::Linear;
|
||||||
pitch = size.width * BytesPerBlock(format);
|
pitch = size.width * BytesPerBlock(format);
|
||||||
} else if (regs.zeta.tile_mode.is_3d) {
|
} else if (regs.zeta.tile_mode.dim_control ==
|
||||||
|
Maxwell3D::Regs::TileMode::DimensionControl::DepthDefinesDepth) {
|
||||||
ASSERT(regs.zeta.tile_mode.is_pitch_linear == 0);
|
ASSERT(regs.zeta.tile_mode.is_pitch_linear == 0);
|
||||||
|
ASSERT(regs.zeta_size.dim_control ==
|
||||||
|
Maxwell3D::Regs::ZetaSize::DimensionControl::ArraySizeOne);
|
||||||
type = ImageType::e3D;
|
type = ImageType::e3D;
|
||||||
size.depth = regs.zeta_depth;
|
size.depth = regs.zeta_size.depth;
|
||||||
} else {
|
} else {
|
||||||
|
ASSERT(regs.zeta_size.dim_control ==
|
||||||
|
Maxwell3D::Regs::ZetaSize::DimensionControl::DepthDefinesArray);
|
||||||
rescaleable = block.depth == 0;
|
rescaleable = block.depth == 0;
|
||||||
downscaleable = size.height > 512;
|
downscaleable = size.height > 512;
|
||||||
type = ImageType::e2D;
|
type = ImageType::e2D;
|
||||||
resources.layers = regs.zeta_depth;
|
resources.layers = regs.zeta_size.depth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,15 +189,16 @@ typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) {
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::SynchronizeGraphicsDescriptors() {
|
void TextureCache<P>::SynchronizeGraphicsDescriptors() {
|
||||||
using SamplerIndex = Tegra::Engines::Maxwell3D::Regs::SamplerIndex;
|
using SamplerBinding = Tegra::Engines::Maxwell3D::Regs::SamplerBinding;
|
||||||
const bool linked_tsc = maxwell3d->regs.sampler_index == SamplerIndex::ViaHeaderIndex;
|
const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
|
||||||
const u32 tic_limit = maxwell3d->regs.tic.limit;
|
const u32 tic_limit = maxwell3d->regs.tex_header.limit;
|
||||||
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tsc.limit;
|
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
|
||||||
if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tsc.Address(),
|
if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tex_sampler.Address(),
|
||||||
tsc_limit)) {
|
tsc_limit)) {
|
||||||
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) {
|
if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tex_header.Address(),
|
||||||
|
tic_limit)) {
|
||||||
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,8 +353,8 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
|
||||||
down_shift = Settings::values.resolution_info.down_shift;
|
down_shift = Settings::values.resolution_info.down_shift;
|
||||||
}
|
}
|
||||||
render_targets.size = Extent2D{
|
render_targets.size = Extent2D{
|
||||||
(maxwell3d->regs.render_area.width * up_scale) >> down_shift,
|
(maxwell3d->regs.surface_clip.width * up_scale) >> down_shift,
|
||||||
(maxwell3d->regs.render_area.height * up_scale) >> down_shift,
|
(maxwell3d->regs.surface_clip.height * up_scale) >> down_shift,
|
||||||
};
|
};
|
||||||
render_targets.is_rescaled = is_rescaling;
|
render_targets.is_rescaled = is_rescaling;
|
||||||
|
|
||||||
|
@ -1980,7 +1981,7 @@ bool TextureCache<P>::IsFullClear(ImageViewId id) {
|
||||||
// Images with multiple resources can't be cleared in a single call
|
// Images with multiple resources can't be cleared in a single call
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (regs.clear_flags.scissor == 0) {
|
if (regs.clear_control.use_scissor == 0) {
|
||||||
// If scissor testing is disabled, the clear is always full
|
// If scissor testing is disabled, the clear is always full
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,51 +15,51 @@ namespace VideoCommon {
|
||||||
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
|
std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
|
||||||
const TransformFeedbackState& state) {
|
const TransformFeedbackState& state) {
|
||||||
static constexpr std::array VECTORS{
|
static constexpr std::array VECTORS{
|
||||||
28, // gl_Position
|
28U, // gl_Position
|
||||||
32, // Generic 0
|
32U, // Generic 0
|
||||||
36, // Generic 1
|
36U, // Generic 1
|
||||||
40, // Generic 2
|
40U, // Generic 2
|
||||||
44, // Generic 3
|
44U, // Generic 3
|
||||||
48, // Generic 4
|
48U, // Generic 4
|
||||||
52, // Generic 5
|
52U, // Generic 5
|
||||||
56, // Generic 6
|
56U, // Generic 6
|
||||||
60, // Generic 7
|
60U, // Generic 7
|
||||||
64, // Generic 8
|
64U, // Generic 8
|
||||||
68, // Generic 9
|
68U, // Generic 9
|
||||||
72, // Generic 10
|
72U, // Generic 10
|
||||||
76, // Generic 11
|
76U, // Generic 11
|
||||||
80, // Generic 12
|
80U, // Generic 12
|
||||||
84, // Generic 13
|
84U, // Generic 13
|
||||||
88, // Generic 14
|
88U, // Generic 14
|
||||||
92, // Generic 15
|
92U, // Generic 15
|
||||||
96, // Generic 16
|
96U, // Generic 16
|
||||||
100, // Generic 17
|
100U, // Generic 17
|
||||||
104, // Generic 18
|
104U, // Generic 18
|
||||||
108, // Generic 19
|
108U, // Generic 19
|
||||||
112, // Generic 20
|
112U, // Generic 20
|
||||||
116, // Generic 21
|
116U, // Generic 21
|
||||||
120, // Generic 22
|
120U, // Generic 22
|
||||||
124, // Generic 23
|
124U, // Generic 23
|
||||||
128, // Generic 24
|
128U, // Generic 24
|
||||||
132, // Generic 25
|
132U, // Generic 25
|
||||||
136, // Generic 26
|
136U, // Generic 26
|
||||||
140, // Generic 27
|
140U, // Generic 27
|
||||||
144, // Generic 28
|
144U, // Generic 28
|
||||||
148, // Generic 29
|
148U, // Generic 29
|
||||||
152, // Generic 30
|
152U, // Generic 30
|
||||||
156, // Generic 31
|
156U, // Generic 31
|
||||||
160, // gl_FrontColor
|
160U, // gl_FrontColor
|
||||||
164, // gl_FrontSecondaryColor
|
164U, // gl_FrontSecondaryColor
|
||||||
160, // gl_BackColor
|
160U, // gl_BackColor
|
||||||
164, // gl_BackSecondaryColor
|
164U, // gl_BackSecondaryColor
|
||||||
192, // gl_TexCoord[0]
|
192U, // gl_TexCoord[0]
|
||||||
196, // gl_TexCoord[1]
|
196U, // gl_TexCoord[1]
|
||||||
200, // gl_TexCoord[2]
|
200U, // gl_TexCoord[2]
|
||||||
204, // gl_TexCoord[3]
|
204U, // gl_TexCoord[3]
|
||||||
208, // gl_TexCoord[4]
|
208U, // gl_TexCoord[4]
|
||||||
212, // gl_TexCoord[5]
|
212U, // gl_TexCoord[5]
|
||||||
216, // gl_TexCoord[6]
|
216U, // gl_TexCoord[6]
|
||||||
220, // gl_TexCoord[7]
|
220U, // gl_TexCoord[7]
|
||||||
};
|
};
|
||||||
std::vector<Shader::TransformFeedbackVarying> xfb(256);
|
std::vector<Shader::TransformFeedbackVarying> xfb(256);
|
||||||
for (size_t buffer = 0; buffer < state.layouts.size(); ++buffer) {
|
for (size_t buffer = 0; buffer < state.layouts.size(); ++buffer) {
|
||||||
|
@ -68,8 +68,20 @@ std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
|
||||||
const u32 varying_count = layout.varying_count;
|
const u32 varying_count = layout.varying_count;
|
||||||
u32 highest = 0;
|
u32 highest = 0;
|
||||||
for (u32 offset = 0; offset < varying_count; ++offset) {
|
for (u32 offset = 0; offset < varying_count; ++offset) {
|
||||||
const u32 base_offset = offset;
|
const auto get_attribute = [&locations](u32 index) -> u32 {
|
||||||
const u8 location = locations[offset];
|
switch (index % 4) {
|
||||||
|
case 0:
|
||||||
|
return locations[index / 4].attribute0.Value();
|
||||||
|
case 1:
|
||||||
|
return locations[index / 4].attribute1.Value();
|
||||||
|
case 2:
|
||||||
|
return locations[index / 4].attribute2.Value();
|
||||||
|
case 3:
|
||||||
|
return locations[index / 4].attribute3.Value();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
UNIMPLEMENTED_IF_MSG(layout.stream != 0, "Stream is not zero: {}", layout.stream);
|
UNIMPLEMENTED_IF_MSG(layout.stream != 0, "Stream is not zero: {}", layout.stream);
|
||||||
Shader::TransformFeedbackVarying varying{
|
Shader::TransformFeedbackVarying varying{
|
||||||
|
@ -78,16 +90,18 @@ std::vector<Shader::TransformFeedbackVarying> MakeTransformFeedbackVaryings(
|
||||||
.offset = offset * 4,
|
.offset = offset * 4,
|
||||||
.components = 1,
|
.components = 1,
|
||||||
};
|
};
|
||||||
if (std::ranges::find(VECTORS, Common::AlignDown(location, 4)) != VECTORS.end()) {
|
const u32 base_offset = offset;
|
||||||
UNIMPLEMENTED_IF_MSG(location % 4 != 0, "Unaligned TFB");
|
const auto attribute{get_attribute(offset)};
|
||||||
|
if (std::ranges::find(VECTORS, Common::AlignDown(attribute, 4)) != VECTORS.end()) {
|
||||||
|
UNIMPLEMENTED_IF_MSG(attribute % 4 != 0, "Unaligned TFB {}", attribute);
|
||||||
|
|
||||||
const u8 base_index = location / 4;
|
const auto base_index = attribute / 4;
|
||||||
while (offset + 1 < varying_count && base_index == locations[offset + 1] / 4) {
|
while (offset + 1 < varying_count && base_index == get_attribute(offset + 1) / 4) {
|
||||||
++offset;
|
++offset;
|
||||||
++varying.components;
|
++varying.components;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfb[location] = varying;
|
xfb[attribute] = varying;
|
||||||
highest = std::max(highest, (base_offset + varying.components) * 4);
|
highest = std::max(highest, (base_offset + varying.components) * 4);
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_IF(highest != layout.stride);
|
UNIMPLEMENTED_IF(highest != layout.stride);
|
||||||
|
|
|
@ -19,7 +19,8 @@ struct TransformFeedbackState {
|
||||||
u32 stride;
|
u32 stride;
|
||||||
};
|
};
|
||||||
std::array<Layout, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> layouts;
|
std::array<Layout, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> layouts;
|
||||||
std::array<std::array<u8, 128>, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
|
std::array<std::array<Tegra::Engines::Maxwell3D::Regs::StreamOutLayout, 32>,
|
||||||
|
Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
|
||||||
varyings;
|
varyings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue